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 android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.content.pm.PackageManager.NameNotFoundException;
24 import android.content.res.Resources;
25 import android.os.Bundle;
26 import android.os.UserHandle;
27 import android.preference.Preference;
28 import android.preference.PreferenceActivity;
29 import android.telephony.CellBroadcastMessage;
30 import android.telephony.PhoneNumberUtils;
31 import android.telephony.PhoneStateListener;
32 import android.telephony.ServiceState;
33 import android.telephony.SignalStrength;
34 import android.telephony.SubscriptionInfo;
35 import android.telephony.SubscriptionManager;
36 import android.telephony.TelephonyManager;
37 import android.text.TextUtils;
38 import android.util.Log;
40 import com.android.internal.logging.MetricsLogger;
41 import com.android.internal.telephony.DefaultPhoneNotifier;
42 import com.android.internal.telephony.Phone;
43 import com.android.internal.telephony.PhoneFactory;
44 import com.android.settings.InstrumentedPreferenceActivity;
45 import com.android.settings.R;
46 import com.android.settings.Utils;
48 import android.view.View;
49 import android.widget.ListView;
50 import android.widget.TabHost;
51 import android.widget.TabHost.OnTabChangeListener;
52 import android.widget.TabHost.TabContentFactory;
53 import android.widget.TabHost.TabSpec;
54 import android.widget.TabWidget;
56 import java.util.ArrayList;
57 import java.util.List;
61 * Display the following information
65 * # Device Id (IMEI in GSM and MEID in CDMA)
67 * # Operator info (area info cell broadcast for Brazil)
71 public class SimStatus extends InstrumentedPreferenceActivity {
72 private static final String TAG = "SimStatus";
74 private static final String KEY_DATA_STATE = "data_state";
75 private static final String KEY_SERVICE_STATE = "service_state";
76 private static final String KEY_OPERATOR_NAME = "operator_name";
77 private static final String KEY_ROAMING_STATE = "roaming_state";
78 private static final String KEY_NETWORK_TYPE = "network_type";
79 private static final String KEY_LATEST_AREA_INFO = "latest_area_info";
80 private static final String KEY_PHONE_NUMBER = "number";
81 private static final String KEY_SIGNAL_STRENGTH = "signal_strength";
82 private static final String KEY_IMEI = "imei";
83 private static final String KEY_IMEI_SV = "imei_sv";
84 private static final String COUNTRY_ABBREVIATION_BRAZIL = "br";
86 static final String CB_AREA_INFO_RECEIVED_ACTION =
87 "android.cellbroadcastreceiver.CB_AREA_INFO_RECEIVED";
89 static final String GET_LATEST_CB_AREA_INFO_ACTION =
90 "android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO";
92 // Require the sender to have this permission to prevent third-party spoofing.
93 static final String CB_AREA_INFO_SENDER_PERMISSION =
94 "android.permission.RECEIVE_EMERGENCY_BROADCAST";
97 private TelephonyManager mTelephonyManager;
98 private Phone mPhone = null;
99 private Resources mRes;
100 private Preference mSignalStrength;
101 private SubscriptionInfo mSir;
102 private boolean mShowLatestAreaInfo;
104 // Default summary for items
105 private String mDefaultText;
107 private TabHost mTabHost;
108 private TabWidget mTabWidget;
109 private ListView mListView;
110 private List<SubscriptionInfo> mSelectableSubInfos;
112 private PhoneStateListener mPhoneStateListener;
113 private BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() {
115 public void onReceive(Context context, Intent intent) {
116 String action = intent.getAction();
117 if (CB_AREA_INFO_RECEIVED_ACTION.equals(action)) {
118 Bundle extras = intent.getExtras();
119 if (extras == null) {
122 CellBroadcastMessage cbMessage = (CellBroadcastMessage) extras.get("message");
123 if (cbMessage != null
124 && cbMessage.getServiceCategory() == 50
125 && mSir.getSubscriptionId() == cbMessage.getSubId()) {
126 String latestAreaInfo = cbMessage.getMessageBody();
127 updateAreaInfo(latestAreaInfo);
134 protected void onCreate(Bundle icicle) {
135 super.onCreate(icicle);
136 mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
138 mSelectableSubInfos = SubscriptionManager.from(this).getActiveSubscriptionInfoList();
140 addPreferencesFromResource(R.xml.device_info_sim_status);
142 mRes = getResources();
143 mDefaultText = mRes.getString(R.string.device_info_default);
144 // Note - missing in zaku build, be careful later...
145 mSignalStrength = findPreference(KEY_SIGNAL_STRENGTH);
147 if (mSelectableSubInfos == null) {
150 mSir = mSelectableSubInfos.size() > 0 ? mSelectableSubInfos.get(0) : null;
152 if (mSelectableSubInfos.size() > 1) {
153 setContentView(com.android.internal.R.layout.common_tab_settings);
155 mTabHost = (TabHost) findViewById(android.R.id.tabhost);
156 mTabWidget = (TabWidget) findViewById(android.R.id.tabs);
157 mListView = (ListView) findViewById(android.R.id.list);
160 mTabHost.setOnTabChangedListener(mTabListener);
161 mTabHost.clearAllTabs();
163 for (int i = 0; i < mSelectableSubInfos.size(); i++) {
164 mTabHost.addTab(buildTabSpec(String.valueOf(i),
165 String.valueOf(mSelectableSubInfos.get(i).getDisplayName())));
173 protected int getMetricsCategory() {
174 return MetricsLogger.DEVICEINFO_SIM_STATUS;
178 protected void onResume() {
180 if (mPhone != null) {
183 updateSignalStrength(mPhone.getSignalStrength());
184 updateServiceState(mPhone.getServiceState());
186 mTelephonyManager.listen(mPhoneStateListener,
187 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
188 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
189 | PhoneStateListener.LISTEN_SERVICE_STATE);
190 if (mShowLatestAreaInfo) {
191 registerReceiver(mAreaInfoReceiver, new IntentFilter(CB_AREA_INFO_RECEIVED_ACTION),
192 CB_AREA_INFO_SENDER_PERMISSION, null);
193 // Ask CellBroadcastReceiver to broadcast the latest area info received
194 Intent getLatestIntent = new Intent(GET_LATEST_CB_AREA_INFO_ACTION);
195 sendBroadcastAsUser(getLatestIntent, UserHandle.ALL,
196 CB_AREA_INFO_SENDER_PERMISSION);
202 public void onPause() {
205 if (mPhone != null) {
206 mTelephonyManager.listen(mPhoneStateListener,
207 PhoneStateListener.LISTEN_NONE);
209 if (mShowLatestAreaInfo) {
210 unregisterReceiver(mAreaInfoReceiver);
215 * Removes the specified preference, if it exists.
216 * @param key the key for the Preference item
218 private void removePreferenceFromScreen(String key) {
219 Preference pref = findPreference(key);
221 getPreferenceScreen().removePreference(pref);
225 private void setSummaryText(String key, String text) {
226 if (TextUtils.isEmpty(text)) {
229 // some preferences may be missing
230 final Preference preference = findPreference(key);
231 if (preference != null) {
232 preference.setSummary(text);
236 private void updateNetworkType() {
237 // Whether EDGE, UMTS, etc...
238 String networktype = null;
239 final int subId = mSir.getSubscriptionId();
240 final int actualDataNetworkType = mTelephonyManager.getDataNetworkType(
241 mSir.getSubscriptionId());
242 final int actualVoiceNetworkType = mTelephonyManager.getVoiceNetworkType(
243 mSir.getSubscriptionId());
244 if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualDataNetworkType) {
245 networktype = mTelephonyManager.getNetworkTypeName(actualDataNetworkType);
246 } else if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualVoiceNetworkType) {
247 networktype = mTelephonyManager.getNetworkTypeName(actualVoiceNetworkType);
250 boolean show4GForLTE = false;
252 Context con = createPackageContext("com.android.systemui", 0);
253 int id = con.getResources().getIdentifier("config_show4GForLTE",
254 "bool", "com.android.systemui");
255 show4GForLTE = con.getResources().getBoolean(id);
256 } catch (NameNotFoundException e) {
257 Log.e(TAG, "NameNotFoundException for show4GFotLTE");
260 if (networktype != null && networktype.equals("LTE") && show4GForLTE) {
263 setSummaryText(KEY_NETWORK_TYPE, networktype);
266 private void updateDataState() {
268 DefaultPhoneNotifier.convertDataState(mPhone.getDataConnectionState());
270 String display = mRes.getString(R.string.radioInfo_unknown);
273 case TelephonyManager.DATA_CONNECTED:
274 display = mRes.getString(R.string.radioInfo_data_connected);
276 case TelephonyManager.DATA_SUSPENDED:
277 display = mRes.getString(R.string.radioInfo_data_suspended);
279 case TelephonyManager.DATA_CONNECTING:
280 display = mRes.getString(R.string.radioInfo_data_connecting);
282 case TelephonyManager.DATA_DISCONNECTED:
283 display = mRes.getString(R.string.radioInfo_data_disconnected);
287 setSummaryText(KEY_DATA_STATE, display);
290 private void updateServiceState(ServiceState serviceState) {
291 final int state = serviceState.getState();
292 String display = mRes.getString(R.string.radioInfo_unknown);
295 case ServiceState.STATE_IN_SERVICE:
296 display = mRes.getString(R.string.radioInfo_service_in);
298 case ServiceState.STATE_OUT_OF_SERVICE:
299 // Set signal strength to 0 when service state is STATE_OUT_OF_SERVICE
300 mSignalStrength.setSummary("0");
301 case ServiceState.STATE_EMERGENCY_ONLY:
302 // Set summary string of service state to radioInfo_service_out when
303 // service state is both STATE_OUT_OF_SERVICE & STATE_EMERGENCY_ONLY
304 display = mRes.getString(R.string.radioInfo_service_out);
306 case ServiceState.STATE_POWER_OFF:
307 display = mRes.getString(R.string.radioInfo_service_off);
308 // Also set signal strength to 0
309 mSignalStrength.setSummary("0");
313 setSummaryText(KEY_SERVICE_STATE, display);
315 if (serviceState.getRoaming()) {
316 setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_in));
318 setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_not));
320 setSummaryText(KEY_OPERATOR_NAME, serviceState.getOperatorAlphaLong());
323 private void updateAreaInfo(String areaInfo) {
324 if (areaInfo != null) {
325 setSummaryText(KEY_LATEST_AREA_INFO, areaInfo);
329 void updateSignalStrength(SignalStrength signalStrength) {
330 if (mSignalStrength != null) {
331 final int state = mPhone.getServiceState().getState();
332 Resources r = getResources();
334 if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
335 (ServiceState.STATE_POWER_OFF == state)) {
336 mSignalStrength.setSummary("0");
340 int signalDbm = signalStrength.getDbm();
341 int signalAsu = signalStrength.getAsuLevel();
343 if (-1 == signalDbm) {
347 if (-1 == signalAsu) {
351 mSignalStrength.setSummary(r.getString(R.string.sim_signal_strength,
352 signalDbm, signalAsu));
356 private void updatePreference() {
357 if (mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) {
358 // only show area info when SIM country is Brazil
359 if (COUNTRY_ABBREVIATION_BRAZIL.equals(mTelephonyManager.getSimCountryIso(
360 mSir.getSubscriptionId()))) {
361 mShowLatestAreaInfo = true;
365 String rawNumber = mTelephonyManager.getLine1NumberForSubscriber(mSir.getSubscriptionId());
366 String formattedNumber = null;
367 if (!TextUtils.isEmpty(rawNumber)) {
368 formattedNumber = PhoneNumberUtils.formatNumber(rawNumber);
370 // If formattedNumber is null or empty, it'll display as "Unknown".
371 setSummaryText(KEY_PHONE_NUMBER, formattedNumber);
372 setSummaryText(KEY_IMEI, mPhone.getImei());
373 setSummaryText(KEY_IMEI_SV, mPhone.getDeviceSvn());
375 if (!mShowLatestAreaInfo) {
376 removePreferenceFromScreen(KEY_LATEST_AREA_INFO);
380 private void updatePhoneInfos() {
382 final Phone phone = PhoneFactory.getPhone(SubscriptionManager.getPhoneId(
383 mSir.getSubscriptionId()));
384 if (UserHandle.myUserId() == UserHandle.USER_OWNER
385 && SubscriptionManager.isValidSubscriptionId(mSir.getSubscriptionId())) {
387 Log.e(TAG, "Unable to locate a phone object for the given Subscription ID.");
392 mPhoneStateListener = new PhoneStateListener(mSir.getSubscriptionId()) {
394 public void onDataConnectionStateChanged(int state) {
400 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
401 updateSignalStrength(signalStrength);
405 public void onServiceStateChanged(ServiceState serviceState) {
406 updateServiceState(serviceState);
412 private OnTabChangeListener mTabListener = new OnTabChangeListener() {
414 public void onTabChanged(String tabId) {
415 final int slotId = Integer.parseInt(tabId);
416 mSir = mSelectableSubInfos.get(slotId);
418 // The User has changed tab; update the SIM information.
420 mTelephonyManager.listen(mPhoneStateListener,
421 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
422 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
423 | PhoneStateListener.LISTEN_SERVICE_STATE);
430 private TabContentFactory mEmptyTabContent = new TabContentFactory() {
432 public View createTabContent(String tag) {
433 return new View(mTabHost.getContext());
437 private TabSpec buildTabSpec(String tag, String title) {
438 return mTabHost.newTabSpec(tag).setIndicator(title).setContent(