2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.deviceinfo;
19 import static android.content.Context.CARRIER_CONFIG_SERVICE;
20 import static android.content.Context.TELEPHONY_SERVICE;
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;
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;
63 import java.util.List;
67 * Display the following information
71 * # Device Id (IMEI in GSM and MEID in CDMA)
73 * # Operator info (area update info cell broadcast)
77 public class SimStatus extends SettingsPreferenceFragment {
78 private static final String TAG = "SimStatus";
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";
92 static private final String CB_AREA_INFO_RECEIVED_ACTION =
93 "com.android.cellbroadcastreceiver.CB_AREA_INFO_RECEIVED";
95 static private final String GET_LATEST_CB_AREA_INFO_ACTION =
96 "com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO";
98 static private final String CELL_BROADCAST_RECEIVER_APP = "com.android.cellbroadcastreceiver";
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;
109 // Default summary for items
110 private String mDefaultText;
112 private TabHost mTabHost;
113 private TabWidget mTabWidget;
114 private ListView mListView;
115 private List<SubscriptionInfo> mSelectableSubInfos;
117 private PhoneStateListener mPhoneStateListener;
119 // Once the cell broadcast configuration is moved into telephony framework,
120 private final BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() {
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) {
129 CellBroadcastMessage cbMessage = (CellBroadcastMessage) extras.get("message");
130 if (cbMessage != null && mSir.getSubscriptionId() == cbMessage.getSubId()) {
131 String latestAreaInfo = cbMessage.getMessageBody();
132 updateAreaInfo(latestAreaInfo);
139 public void onCreate(Bundle icicle) {
140 super.onCreate(icicle);
141 mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
142 mCarrierConfigManager = (CarrierConfigManager) getSystemService(CARRIER_CONFIG_SERVICE);
144 mSelectableSubInfos = SubscriptionManager.from(getContext())
145 .getActiveSubscriptionInfoList();
147 addPreferencesFromResource(R.xml.device_info_sim_status);
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);
156 public View onCreateView(LayoutInflater inflater, ViewGroup container,
157 Bundle savedInstanceState) {
158 if (mSelectableSubInfos == null) {
161 mSir = mSelectableSubInfos.size() > 0 ? mSelectableSubInfos.get(0) : null;
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);
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);
176 mTabHost.setOnTabChangedListener(mTabListener);
177 mTabHost.clearAllTabs();
179 for (int i = 0; i < mSelectableSubInfos.size(); i++) {
180 mTabHost.addTab(buildTabSpec(String.valueOf(i),
181 String.valueOf(mSelectableSubInfos.get(i).getDisplayName())));
186 return super.onCreateView(inflater, container, savedInstanceState);
190 public void onViewCreated(View view, Bundle savedInstanceState) {
191 super.onViewCreated(view, savedInstanceState);
197 public int getMetricsCategory() {
198 return MetricsEvent.DEVICEINFO_SIM_STATUS;
202 public void onResume() {
204 if (mPhone != null) {
207 updateSignalStrength(mPhone.getSignalStrength());
208 updateServiceState(mPhone.getServiceState());
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);
228 public void onPause() {
231 if (mPhone != null) {
232 mTelephonyManager.listen(mPhoneStateListener,
233 PhoneStateListener.LISTEN_NONE);
235 if (mShowLatestAreaInfo) {
236 getContext().unregisterReceiver(mAreaInfoReceiver);
241 * Removes the specified preference, if it exists.
242 * @param key the key for the Preference item
244 private void removePreferenceFromScreen(String key) {
245 Preference pref = findPreference(key);
247 getPreferenceScreen().removePreference(pref);
251 private void setSummaryText(String key, String text) {
252 if (TextUtils.isEmpty(text)) {
255 // some preferences may be missing
256 final Preference preference = findPreference(key);
257 if (preference != null) {
258 preference.setSummary(text);
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);
276 boolean show4GForLTE = false;
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");
286 if (networktype != null && networktype.equals("LTE") && show4GForLTE) {
289 setSummaryText(KEY_NETWORK_TYPE, networktype);
292 private void updateDataState() {
294 PhoneConstantConversions.convertDataState(mPhone.getDataConnectionState());
296 String display = mRes.getString(R.string.radioInfo_unknown);
299 case TelephonyManager.DATA_CONNECTED:
300 display = mRes.getString(R.string.radioInfo_data_connected);
302 case TelephonyManager.DATA_SUSPENDED:
303 display = mRes.getString(R.string.radioInfo_data_suspended);
305 case TelephonyManager.DATA_CONNECTING:
306 display = mRes.getString(R.string.radioInfo_data_connecting);
308 case TelephonyManager.DATA_DISCONNECTED:
309 display = mRes.getString(R.string.radioInfo_data_disconnected);
313 setSummaryText(KEY_DATA_STATE, display);
316 private void updateServiceState(ServiceState serviceState) {
317 final int state = serviceState.getState();
318 String display = mRes.getString(R.string.radioInfo_unknown);
321 case ServiceState.STATE_IN_SERVICE:
322 display = mRes.getString(R.string.radioInfo_service_in);
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);
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");
339 setSummaryText(KEY_SERVICE_STATE, display);
341 if (serviceState.getRoaming()) {
342 setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_in));
344 setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_not));
346 setSummaryText(KEY_OPERATOR_NAME, serviceState.getOperatorAlphaLong());
349 private void updateAreaInfo(String areaInfo) {
350 if (areaInfo != null) {
351 setSummaryText(KEY_LATEST_AREA_INFO, areaInfo);
355 void updateSignalStrength(SignalStrength signalStrength) {
356 if (mSignalStrength != null) {
357 final int state = mPhone.getServiceState().getState();
359 if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
360 (ServiceState.STATE_POWER_OFF == state)) {
361 mSignalStrength.setSummary("0");
365 int signalDbm = signalStrength.getDbm();
366 int signalAsu = signalStrength.getAsuLevel();
368 if (-1 == signalDbm) {
372 if (-1 == signalAsu) {
376 mSignalStrength.setSummary(mRes.getString(R.string.sim_signal_strength,
377 signalDbm, signalAsu));
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);
386 PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(
387 mSir.getSubscriptionId());
388 mShowICCID = carrierConfig.getBoolean(
389 CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL);
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());
399 removePreferenceFromScreen(KEY_ICCID);
401 // Get ICCID, which is SIM serial number
402 String iccid = mTelephonyManager.getSimSerialNumber(mSir.getSubscriptionId());
403 setSummaryText(KEY_ICCID, iccid);
406 if (!mShowLatestAreaInfo) {
407 removePreferenceFromScreen(KEY_LATEST_AREA_INFO);
410 boolean hideSignalStrength = carrierConfig.getBoolean(
411 CarrierConfigManager.KEY_HIDE_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL);
412 if (hideSignalStrength) {
413 removePreferenceFromScreen(KEY_SIGNAL_STRENGTH);
417 private void updatePhoneInfos() {
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())) {
425 Log.e(TAG, "Unable to locate a phone object for the given Subscription ID.");
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;
436 mPhoneStateListener = new PhoneStateListener(mSir.getSubscriptionId()) {
438 public void onDataConnectionStateChanged(int state) {
444 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
445 updateSignalStrength(signalStrength);
449 public void onServiceStateChanged(ServiceState serviceState) {
450 updateServiceState(serviceState);
456 private OnTabChangeListener mTabListener = new OnTabChangeListener() {
458 public void onTabChanged(String tabId) {
459 final int slotId = Integer.parseInt(tabId);
460 mSir = mSelectableSubInfos.get(slotId);
462 // The User has changed tab; update the SIM information.
464 mTelephonyManager.listen(mPhoneStateListener,
465 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
466 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
467 | PhoneStateListener.LISTEN_SERVICE_STATE);
474 private TabContentFactory mEmptyTabContent = new TabContentFactory() {
476 public View createTabContent(String tag) {
477 return new View(mTabHost.getContext());
481 private TabSpec buildTabSpec(String tag, String title) {
482 return mTabHost.newTabSpec(tag).setIndicator(title).setContent(