OSDN Git Service

Merge "Hide signal strength when told by carrier"
[android-x86/packages-apps-Settings.git] / src / com / android / settings / deviceinfo / SimStatus.java
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.settings.deviceinfo;
18
19 import static android.content.Context.CARRIER_CONFIG_SERVICE;
20 import static android.content.Context.TELEPHONY_SERVICE;
21
22 import android.Manifest;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.pm.PackageManager.NameNotFoundException;
28 import android.content.res.Resources;
29 import android.os.Bundle;
30 import android.os.PersistableBundle;
31 import android.os.UserHandle;
32 import android.os.UserManager;
33 import android.support.v7.preference.Preference;
34 import android.telephony.CarrierConfigManager;
35 import android.telephony.CellBroadcastMessage;
36 import android.telephony.PhoneStateListener;
37 import android.telephony.ServiceState;
38 import android.telephony.SignalStrength;
39 import android.telephony.SubscriptionInfo;
40 import android.telephony.SubscriptionManager;
41 import android.telephony.TelephonyManager;
42 import android.text.TextUtils;
43 import android.util.Log;
44 import android.view.LayoutInflater;
45 import android.view.View;
46 import android.view.ViewGroup;
47 import android.widget.ListView;
48 import android.widget.TabHost;
49 import android.widget.TabHost.OnTabChangeListener;
50 import android.widget.TabHost.TabContentFactory;
51 import android.widget.TabHost.TabSpec;
52 import android.widget.TabWidget;
53
54 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
55 import com.android.internal.telephony.Phone;
56 import com.android.internal.telephony.PhoneConstantConversions;
57 import com.android.internal.telephony.PhoneFactory;
58 import com.android.settings.R;
59 import com.android.settings.SettingsPreferenceFragment;
60 import com.android.settings.Utils;
61 import com.android.settingslib.DeviceInfoUtils;
62
63 import java.util.List;
64
65
66 /**
67  * Display the following information
68  * # Phone Number
69  * # Network
70  * # Roaming
71  * # Device Id (IMEI in GSM and MEID in CDMA)
72  * # Network type
73  * # Operator info (area update info cell broadcast)
74  * # Signal Strength
75  *
76  */
77 public class SimStatus extends SettingsPreferenceFragment {
78     private static final String TAG = "SimStatus";
79
80     private static final String KEY_DATA_STATE = "data_state";
81     private static final String KEY_SERVICE_STATE = "service_state";
82     private static final String KEY_OPERATOR_NAME = "operator_name";
83     private static final String KEY_ROAMING_STATE = "roaming_state";
84     private static final String KEY_NETWORK_TYPE = "network_type";
85     private static final String KEY_LATEST_AREA_INFO = "latest_area_info";
86     private static final String KEY_PHONE_NUMBER = "number";
87     private static final String KEY_SIGNAL_STRENGTH = "signal_strength";
88     private static final String KEY_IMEI = "imei";
89     private static final String KEY_IMEI_SV = "imei_sv";
90     private static final String KEY_ICCID = "iccid";
91
92     static private final String CB_AREA_INFO_RECEIVED_ACTION =
93             "com.android.cellbroadcastreceiver.CB_AREA_INFO_RECEIVED";
94
95     static private final String GET_LATEST_CB_AREA_INFO_ACTION =
96             "com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO";
97
98     static private final String CELL_BROADCAST_RECEIVER_APP = "com.android.cellbroadcastreceiver";
99
100     private TelephonyManager mTelephonyManager;
101     private CarrierConfigManager mCarrierConfigManager;
102     private Phone mPhone = null;
103     private Resources mRes;
104     private Preference mSignalStrength;
105     private SubscriptionInfo mSir;
106     private boolean mShowLatestAreaInfo;
107     private boolean mShowICCID;
108
109     // Default summary for items
110     private String mDefaultText;
111
112     private TabHost mTabHost;
113     private TabWidget mTabWidget;
114     private ListView mListView;
115     private List<SubscriptionInfo> mSelectableSubInfos;
116
117     private PhoneStateListener mPhoneStateListener;
118
119     // Once the cell broadcast configuration is moved into telephony framework,
120     private final BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() {
121         @Override
122         public void onReceive(Context context, Intent intent) {
123             String action = intent.getAction();
124             if (CB_AREA_INFO_RECEIVED_ACTION.equals(action)) {
125                 Bundle extras = intent.getExtras();
126                 if (extras == null) {
127                     return;
128                 }
129                 CellBroadcastMessage cbMessage = (CellBroadcastMessage) extras.get("message");
130                 if (cbMessage != null && mSir.getSubscriptionId() == cbMessage.getSubId()) {
131                     String latestAreaInfo = cbMessage.getMessageBody();
132                     updateAreaInfo(latestAreaInfo);
133                 }
134             }
135         }
136     };
137
138     @Override
139     public void onCreate(Bundle icicle) {
140         super.onCreate(icicle);
141         mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
142         mCarrierConfigManager = (CarrierConfigManager) getSystemService(CARRIER_CONFIG_SERVICE);
143
144         mSelectableSubInfos = SubscriptionManager.from(getContext())
145                 .getActiveSubscriptionInfoList();
146
147         addPreferencesFromResource(R.xml.device_info_sim_status);
148
149         mRes = getResources();
150         mDefaultText = mRes.getString(R.string.device_info_default);
151         // Note - missing in zaku build, be careful later...
152         mSignalStrength = findPreference(KEY_SIGNAL_STRENGTH);
153     }
154
155     @Override
156     public View onCreateView(LayoutInflater inflater, ViewGroup container,
157             Bundle savedInstanceState) {
158         if (mSelectableSubInfos == null) {
159             mSir = null;
160         } else {
161             mSir = mSelectableSubInfos.size() > 0 ? mSelectableSubInfos.get(0) : null;
162
163             if (mSelectableSubInfos.size() > 1) {
164                 View view = inflater.inflate(R.layout.icc_lock_tabs, container, false);
165                 final ViewGroup prefs_container = (ViewGroup) view.findViewById(
166                         R.id.prefs_container);
167                 Utils.prepareCustomPreferencesList(container, view, prefs_container, false);
168                 View prefs = super.onCreateView(inflater, prefs_container, savedInstanceState);
169                 prefs_container.addView(prefs);
170
171                 mTabHost = (TabHost) view.findViewById(android.R.id.tabhost);
172                 mTabWidget = (TabWidget) view.findViewById(android.R.id.tabs);
173                 mListView = (ListView) view.findViewById(android.R.id.list);
174
175                 mTabHost.setup();
176                 mTabHost.setOnTabChangedListener(mTabListener);
177                 mTabHost.clearAllTabs();
178
179                 for (int i = 0; i < mSelectableSubInfos.size(); i++) {
180                     mTabHost.addTab(buildTabSpec(String.valueOf(i),
181                             String.valueOf(mSelectableSubInfos.get(i).getDisplayName())));
182                 }
183                 return view;
184             }
185         }
186         return super.onCreateView(inflater, container, savedInstanceState);
187     }
188
189     @Override
190     public void onViewCreated(View view, Bundle savedInstanceState) {
191         super.onViewCreated(view, savedInstanceState);
192
193         updatePhoneInfos();
194     }
195
196     @Override
197     public int getMetricsCategory() {
198         return MetricsEvent.DEVICEINFO_SIM_STATUS;
199     }
200
201     @Override
202     public void onResume() {
203         super.onResume();
204         if (mPhone != null) {
205             updatePreference();
206
207             updateSignalStrength(mPhone.getSignalStrength());
208             updateServiceState(mPhone.getServiceState());
209             updateDataState();
210             mTelephonyManager.listen(mPhoneStateListener,
211                     PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
212                     | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
213                     | PhoneStateListener.LISTEN_SERVICE_STATE);
214             if (mShowLatestAreaInfo) {
215                 getContext().registerReceiver(mAreaInfoReceiver,
216                         new IntentFilter(CB_AREA_INFO_RECEIVED_ACTION),
217                         Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, null);
218                 // Ask CellBroadcastReceiver to broadcast the latest area info received
219                 Intent getLatestIntent = new Intent(GET_LATEST_CB_AREA_INFO_ACTION);
220                 getLatestIntent.setPackage(CELL_BROADCAST_RECEIVER_APP);
221                 getContext().sendBroadcastAsUser(getLatestIntent, UserHandle.ALL,
222                         Manifest.permission.RECEIVE_EMERGENCY_BROADCAST);
223             }
224         }
225     }
226
227     @Override
228     public void onPause() {
229         super.onPause();
230
231         if (mPhone != null) {
232             mTelephonyManager.listen(mPhoneStateListener,
233                     PhoneStateListener.LISTEN_NONE);
234         }
235         if (mShowLatestAreaInfo) {
236             getContext().unregisterReceiver(mAreaInfoReceiver);
237         }
238     }
239
240     /**
241      * Removes the specified preference, if it exists.
242      * @param key the key for the Preference item
243      */
244     private void removePreferenceFromScreen(String key) {
245         Preference pref = findPreference(key);
246         if (pref != null) {
247             getPreferenceScreen().removePreference(pref);
248         }
249     }
250
251     private void setSummaryText(String key, String text) {
252         if (TextUtils.isEmpty(text)) {
253             text = mDefaultText;
254         }
255         // some preferences may be missing
256         final Preference preference = findPreference(key);
257         if (preference != null) {
258             preference.setSummary(text);
259         }
260     }
261
262     private void updateNetworkType() {
263         // Whether EDGE, UMTS, etc...
264         String networktype = null;
265         final int subId = mSir.getSubscriptionId();
266         final int actualDataNetworkType = mTelephonyManager.getDataNetworkType(
267                 mSir.getSubscriptionId());
268         final int actualVoiceNetworkType = mTelephonyManager.getVoiceNetworkType(
269                 mSir.getSubscriptionId());
270         if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualDataNetworkType) {
271             networktype = mTelephonyManager.getNetworkTypeName(actualDataNetworkType);
272         } else if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualVoiceNetworkType) {
273             networktype = mTelephonyManager.getNetworkTypeName(actualVoiceNetworkType);
274         }
275
276         boolean show4GForLTE = false;
277         try {
278             Context con = getActivity().createPackageContext("com.android.systemui", 0);
279             int id = con.getResources().getIdentifier("config_show4GForLTE",
280                     "bool", "com.android.systemui");
281             show4GForLTE = con.getResources().getBoolean(id);
282         } catch (NameNotFoundException e) {
283             Log.e(TAG, "NameNotFoundException for show4GFotLTE");
284         }
285
286         if (networktype != null && networktype.equals("LTE") && show4GForLTE) {
287             networktype = "4G";
288         }
289         setSummaryText(KEY_NETWORK_TYPE, networktype);
290     }
291
292     private void updateDataState() {
293         final int state =
294                 PhoneConstantConversions.convertDataState(mPhone.getDataConnectionState());
295
296         String display = mRes.getString(R.string.radioInfo_unknown);
297
298         switch (state) {
299             case TelephonyManager.DATA_CONNECTED:
300                 display = mRes.getString(R.string.radioInfo_data_connected);
301                 break;
302             case TelephonyManager.DATA_SUSPENDED:
303                 display = mRes.getString(R.string.radioInfo_data_suspended);
304                 break;
305             case TelephonyManager.DATA_CONNECTING:
306                 display = mRes.getString(R.string.radioInfo_data_connecting);
307                 break;
308             case TelephonyManager.DATA_DISCONNECTED:
309                 display = mRes.getString(R.string.radioInfo_data_disconnected);
310                 break;
311         }
312
313         setSummaryText(KEY_DATA_STATE, display);
314     }
315
316     private void updateServiceState(ServiceState serviceState) {
317         final int state = serviceState.getState();
318         String display = mRes.getString(R.string.radioInfo_unknown);
319
320         switch (state) {
321             case ServiceState.STATE_IN_SERVICE:
322                 display = mRes.getString(R.string.radioInfo_service_in);
323                 break;
324             case ServiceState.STATE_OUT_OF_SERVICE:
325                 // Set signal strength to 0 when service state is STATE_OUT_OF_SERVICE
326                 mSignalStrength.setSummary("0");
327             case ServiceState.STATE_EMERGENCY_ONLY:
328                 // Set summary string of service state to radioInfo_service_out when
329                 // service state is both STATE_OUT_OF_SERVICE & STATE_EMERGENCY_ONLY
330                 display = mRes.getString(R.string.radioInfo_service_out);
331                 break;
332             case ServiceState.STATE_POWER_OFF:
333                 display = mRes.getString(R.string.radioInfo_service_off);
334                 // Also set signal strength to 0
335                 mSignalStrength.setSummary("0");
336                 break;
337         }
338
339         setSummaryText(KEY_SERVICE_STATE, display);
340
341         if (serviceState.getRoaming()) {
342             setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_in));
343         } else {
344             setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_not));
345         }
346         setSummaryText(KEY_OPERATOR_NAME, serviceState.getOperatorAlphaLong());
347     }
348
349     private void updateAreaInfo(String areaInfo) {
350         if (areaInfo != null) {
351             setSummaryText(KEY_LATEST_AREA_INFO, areaInfo);
352         }
353     }
354
355     void updateSignalStrength(SignalStrength signalStrength) {
356         if (mSignalStrength != null) {
357             final int state = mPhone.getServiceState().getState();
358
359             if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
360                     (ServiceState.STATE_POWER_OFF == state)) {
361                 mSignalStrength.setSummary("0");
362                 return;
363             }
364
365             int signalDbm = signalStrength.getDbm();
366             int signalAsu = signalStrength.getAsuLevel();
367
368             if (-1 == signalDbm) {
369                 signalDbm = 0;
370             }
371
372             if (-1 == signalAsu) {
373                 signalAsu = 0;
374             }
375
376             mSignalStrength.setSummary(mRes.getString(R.string.sim_signal_strength,
377                         signalDbm, signalAsu));
378         }
379     }
380
381     private void updatePreference() {
382         if (mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) {
383             mShowLatestAreaInfo = Resources.getSystem().getBoolean(
384                     com.android.internal.R.bool.config_showAreaUpdateInfoSettings);
385         }
386         PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(
387                 mSir.getSubscriptionId());
388         mShowICCID = carrierConfig.getBoolean(
389                 CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL);
390
391
392         // If formattedNumber is null or empty, it'll display as "Unknown".
393         setSummaryText(KEY_PHONE_NUMBER,
394                 DeviceInfoUtils.getFormattedPhoneNumber(getContext(), mSir));
395         setSummaryText(KEY_IMEI, mPhone.getImei());
396         setSummaryText(KEY_IMEI_SV, mPhone.getDeviceSvn());
397
398         if (!mShowICCID) {
399             removePreferenceFromScreen(KEY_ICCID);
400         } else {
401             // Get ICCID, which is SIM serial number
402             String iccid = mTelephonyManager.getSimSerialNumber(mSir.getSubscriptionId());
403             setSummaryText(KEY_ICCID, iccid);
404         }
405
406         if (!mShowLatestAreaInfo) {
407             removePreferenceFromScreen(KEY_LATEST_AREA_INFO);
408         }
409
410         boolean hideSignalStrength = carrierConfig.getBoolean(
411                 CarrierConfigManager.KEY_HIDE_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL);
412         if (hideSignalStrength) {
413             removePreferenceFromScreen(KEY_SIGNAL_STRENGTH);
414         }
415     }
416
417     private void updatePhoneInfos() {
418         if (mSir != null) {
419             // TODO: http://b/23763013
420             final Phone phone = PhoneFactory.getPhone(SubscriptionManager.getPhoneId(
421                         mSir.getSubscriptionId()));
422             if (UserManager.get(getContext()).isAdminUser()
423                     && SubscriptionManager.isValidSubscriptionId(mSir.getSubscriptionId())) {
424                 if (phone == null) {
425                     Log.e(TAG, "Unable to locate a phone object for the given Subscription ID.");
426                     return;
427                 }
428
429                 mPhone = phone;
430                 // To avoid register multiple listeners when user changes the tab.
431                 if (mPhoneStateListener != null && mTelephonyManager != null) {
432                     mTelephonyManager.listen(mPhoneStateListener,
433                             PhoneStateListener.LISTEN_NONE);
434                     mPhoneStateListener = null;
435                 }
436                 mPhoneStateListener = new PhoneStateListener(mSir.getSubscriptionId()) {
437                     @Override
438                     public void onDataConnectionStateChanged(int state) {
439                         updateDataState();
440                         updateNetworkType();
441                     }
442
443                     @Override
444                     public void onSignalStrengthsChanged(SignalStrength signalStrength) {
445                         updateSignalStrength(signalStrength);
446                     }
447
448                     @Override
449                     public void onServiceStateChanged(ServiceState serviceState) {
450                         updateServiceState(serviceState);
451                     }
452                 };
453             }
454         }
455     }
456     private OnTabChangeListener mTabListener = new OnTabChangeListener() {
457         @Override
458         public void onTabChanged(String tabId) {
459             final int slotId = Integer.parseInt(tabId);
460             mSir = mSelectableSubInfos.get(slotId);
461
462             // The User has changed tab; update the SIM information.
463             updatePhoneInfos();
464             mTelephonyManager.listen(mPhoneStateListener,
465                     PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
466                     | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
467                     | PhoneStateListener.LISTEN_SERVICE_STATE);
468             updateDataState();
469             updateNetworkType();
470             updatePreference();
471         }
472     };
473
474     private TabContentFactory mEmptyTabContent = new TabContentFactory() {
475         @Override
476         public View createTabContent(String tag) {
477             return new View(mTabHost.getContext());
478         }
479     };
480
481     private TabSpec buildTabSpec(String tag, String title) {
482         return mTabHost.newTabSpec(tag).setIndicator(title).setContent(
483                 mEmptyTabContent);
484     }
485 }