OSDN Git Service

Add SIM status string for localizing voice/data strings
[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 android.app.ActionBar;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.content.pm.PackageManager.NameNotFoundException;
25 import android.content.res.Resources;
26 import android.os.Bundle;
27 import android.os.UserHandle;
28 import android.preference.Preference;
29 import android.preference.PreferenceActivity;
30 import android.telephony.CellBroadcastMessage;
31 import android.telephony.PhoneNumberUtils;
32 import android.telephony.PhoneStateListener;
33 import android.telephony.ServiceState;
34 import android.telephony.SignalStrength;
35 import android.telephony.SubscriptionInfo;
36 import android.telephony.SubscriptionManager;
37 import android.telephony.TelephonyManager;
38 import android.text.TextUtils;
39 import android.util.Log;
40 import android.view.MenuItem;
41 import android.view.View;
42 import android.widget.ListView;
43
44 import com.android.internal.logging.MetricsLogger;
45 import com.android.internal.telephony.DefaultPhoneNotifier;
46 import com.android.internal.telephony.Phone;
47 import com.android.internal.telephony.PhoneConstants;
48 import com.android.internal.telephony.PhoneFactory;
49 import com.android.settings.InstrumentedPreferenceActivity;
50 import com.android.settings.R;
51 import com.android.settings.Utils;
52
53 import java.util.ArrayList;
54 import java.util.List;
55
56
57 /**
58  * Display the following information
59  * # Phone Number
60  * # Network
61  * # Roaming
62  * # Network type
63  * # Operator info (area info cell broadcast for Brazil)
64  * # Signal Strength
65  *
66  */
67 public class SimStatus extends InstrumentedPreferenceActivity {
68     private static final String TAG = "SimStatus";
69
70     private static final String KEY_DATA_STATE = "data_state";
71     private static final String KEY_SERVICE_STATE = "service_state";
72     private static final String KEY_OPERATOR_NAME = "operator_name";
73     private static final String KEY_ROAMING_STATE = "roaming_state";
74     private static final String KEY_NETWORK_TYPE = "network_type";
75     private static final String KEY_LATEST_AREA_INFO = "latest_area_info";
76     private static final String KEY_PHONE_NUMBER = "number";
77     private static final String KEY_SIGNAL_STRENGTH = "signal_strength";
78     private static final String COUNTRY_ABBREVIATION_BRAZIL = "br";
79
80     static final String CB_AREA_INFO_RECEIVED_ACTION =
81             "android.cellbroadcastreceiver.CB_AREA_INFO_RECEIVED";
82
83     static final String GET_LATEST_CB_AREA_INFO_ACTION =
84             "android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO";
85
86     // Require the sender to have this permission to prevent third-party spoofing.
87     static final String CB_AREA_INFO_SENDER_PERMISSION =
88             "android.permission.RECEIVE_EMERGENCY_BROADCAST";
89
90     static final String EXTRA_SLOT_ID = "slot_id";
91
92     private TelephonyManager mTelephonyManager;
93     private Phone mPhone = null;
94     private Resources mRes;
95     private Preference mSignalStrength;
96     private SubscriptionInfo mSir;
97     private boolean mShowLatestAreaInfo;
98
99     // Default summary for items
100     private String mDefaultText;
101
102     private PhoneStateListener mPhoneStateListener;
103     private BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() {
104         @Override
105         public void onReceive(Context context, Intent intent) {
106             String action = intent.getAction();
107             if (CB_AREA_INFO_RECEIVED_ACTION.equals(action)) {
108                 Bundle extras = intent.getExtras();
109                 if (extras == null) {
110                     return;
111                 }
112                 CellBroadcastMessage cbMessage = (CellBroadcastMessage) extras.get("message");
113                 if (cbMessage != null
114                         && cbMessage.getServiceCategory() == 50
115                         && mSir.getSubscriptionId() == cbMessage.getSubId()) {
116                     String latestAreaInfo = cbMessage.getMessageBody();
117                     updateAreaInfo(latestAreaInfo);
118                 }
119             }
120         }
121     };
122
123     @Override
124     protected void onCreate(Bundle icicle) {
125         super.onCreate(icicle);
126         mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
127
128         addPreferencesFromResource(R.xml.device_info_sim_status);
129
130         mRes = getResources();
131         mDefaultText = mRes.getString(R.string.device_info_default);
132         // Note - missing in zaku build, be careful later...
133         mSignalStrength = findPreference(KEY_SIGNAL_STRENGTH);
134
135         SubscriptionManager subscriptionManager = SubscriptionManager.from(this);
136         int slotId = getIntent().getIntExtra(EXTRA_SLOT_ID, 0);
137         mSir = subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(slotId);
138
139         updatePhoneInfos();
140
141         if (getIntent().hasExtra(EXTRA_SLOT_ID)) {
142             setTitle(getString(R.string.sim_card_status_title, slotId + 1));
143         }
144
145         ActionBar actionBar = getActionBar();
146         if (actionBar != null) {
147             actionBar.setDisplayHomeAsUpEnabled(true);
148         }
149     }
150
151     @Override
152     protected int getMetricsCategory() {
153         return MetricsLogger.DEVICEINFO_SIM_STATUS;
154     }
155
156     @Override
157     protected void onResume() {
158         super.onResume();
159         if (mPhone != null) {
160             updatePreference();
161
162             updateSignalStrength(mPhone.getSignalStrength());
163             updateServiceState(mPhone.getServiceState());
164             updateDataState();
165             mTelephonyManager.listen(mPhoneStateListener,
166                     PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
167                     | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
168                     | PhoneStateListener.LISTEN_SERVICE_STATE);
169             if (mShowLatestAreaInfo) {
170                 registerReceiver(mAreaInfoReceiver, new IntentFilter(CB_AREA_INFO_RECEIVED_ACTION),
171                         CB_AREA_INFO_SENDER_PERMISSION, null);
172                 // Ask CellBroadcastReceiver to broadcast the latest area info received
173                 Intent getLatestIntent = new Intent(GET_LATEST_CB_AREA_INFO_ACTION);
174                 getLatestIntent.putExtra(PhoneConstants.SUBSCRIPTION_KEY,
175                         mSir.getSubscriptionId());
176                 sendBroadcastAsUser(getLatestIntent, UserHandle.ALL,
177                         CB_AREA_INFO_SENDER_PERMISSION);
178             }
179         }
180     }
181
182     @Override
183     public void onPause() {
184         super.onPause();
185
186         if (mPhone != null) {
187             mTelephonyManager.listen(mPhoneStateListener,
188                     PhoneStateListener.LISTEN_NONE);
189         }
190         if (mShowLatestAreaInfo) {
191             unregisterReceiver(mAreaInfoReceiver);
192         }
193     }
194
195     @Override
196     public boolean onOptionsItemSelected(MenuItem item) {
197         if (item.getItemId() == android.R.id.home) {
198             finish();
199             return true;
200         }
201         return false;
202     }
203
204     /**
205      * Removes the specified preference, if it exists.
206      * @param key the key for the Preference item
207      */
208     private void removePreferenceFromScreen(String key) {
209         Preference pref = findPreference(key);
210         if (pref != null) {
211             getPreferenceScreen().removePreference(pref);
212         }
213     }
214
215     private void setSummaryText(String key, String text) {
216         if (TextUtils.isEmpty(text)) {
217             text = mDefaultText;
218         }
219         // some preferences may be missing
220         final Preference preference = findPreference(key);
221         if (preference != null) {
222             preference.setSummary(text);
223         }
224     }
225
226     private void updateNetworkType() {
227         // Whether EDGE, UMTS, etc...
228         String networktype = null;
229         final int subId = mSir.getSubscriptionId();
230         final int actualDataNetworkType = mTelephonyManager.getDataNetworkType(
231                 mSir.getSubscriptionId());
232         final int actualVoiceNetworkType = mTelephonyManager.getVoiceNetworkType(
233                 mSir.getSubscriptionId());
234         if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualDataNetworkType) {
235             networktype = mTelephonyManager.getNetworkTypeName(actualDataNetworkType);
236         } else if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualVoiceNetworkType) {
237             networktype = mTelephonyManager.getNetworkTypeName(actualVoiceNetworkType);
238         }
239
240         boolean show4GForLTE = false;
241         try {
242             Context con = createPackageContext("com.android.systemui", 0);
243             int id = con.getResources().getIdentifier("config_show4GForLTE",
244                     "bool", "com.android.systemui");
245             show4GForLTE = con.getResources().getBoolean(id);
246         } catch (NameNotFoundException e) {
247             Log.e(TAG, "NameNotFoundException for show4GFotLTE");
248         }
249
250         if (networktype != null && networktype.equals("LTE") && show4GForLTE) {
251             networktype = "4G";
252         }
253         setSummaryText(KEY_NETWORK_TYPE, networktype);
254     }
255
256     private void updateDataState() {
257         final int state =
258                 DefaultPhoneNotifier.convertDataState(mPhone.getDataConnectionState());
259
260         String display = mRes.getString(R.string.radioInfo_unknown);
261
262         switch (state) {
263             case TelephonyManager.DATA_CONNECTED:
264                 display = mRes.getString(R.string.radioInfo_data_connected);
265                 break;
266             case TelephonyManager.DATA_SUSPENDED:
267                 display = mRes.getString(R.string.radioInfo_data_suspended);
268                 break;
269             case TelephonyManager.DATA_CONNECTING:
270                 display = mRes.getString(R.string.radioInfo_data_connecting);
271                 break;
272             case TelephonyManager.DATA_DISCONNECTED:
273                 display = mRes.getString(R.string.radioInfo_data_disconnected);
274                 break;
275         }
276
277         setSummaryText(KEY_DATA_STATE, display);
278     }
279
280     private void updateServiceState(ServiceState serviceState) {
281         final int state = serviceState.getState();
282         final int dataState = mPhone.getServiceState().getDataRegState();
283
284         switch (state) {
285             case ServiceState.STATE_OUT_OF_SERVICE:
286                 // Set signal strength to 0 when service state is STATE_OUT_OF_SERVICE
287                 if (ServiceState.STATE_OUT_OF_SERVICE == dataState) {
288                     mSignalStrength.setSummary("0");
289                 }
290                 break;
291             case ServiceState.STATE_POWER_OFF:
292                 // Also set signal strength to 0
293                 mSignalStrength.setSummary("0");
294                 break;
295         }
296         String voiceDisplay = Utils.getServiceStateString(state, mRes);
297
298         String dataDisplay = Utils.getServiceStateString(dataState, mRes);
299
300         setSummaryText(KEY_SERVICE_STATE, getString(R.string.sim_status_format_string,
301                 voiceDisplay, dataDisplay));
302
303         if (serviceState.getRoaming()) {
304             setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_in));
305         } else {
306             setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_not));
307         }
308         setSummaryText(KEY_OPERATOR_NAME, serviceState.getOperatorAlphaLong());
309     }
310
311     private void updateAreaInfo(String areaInfo) {
312         if (areaInfo != null) {
313             setSummaryText(KEY_LATEST_AREA_INFO, areaInfo);
314         }
315     }
316
317     void updateSignalStrength(SignalStrength signalStrength) {
318         if (mSignalStrength != null) {
319             final int state = mPhone.getServiceState().getState();
320             final int dataState = mPhone.getServiceState().getDataRegState();
321             Resources r = getResources();
322
323             if (((ServiceState.STATE_OUT_OF_SERVICE == state) &&
324                     (ServiceState.STATE_OUT_OF_SERVICE == dataState)) ||
325                     (ServiceState.STATE_POWER_OFF == state)) {
326                 mSignalStrength.setSummary("0");
327                 return;
328             }
329
330             int signalDbm = signalStrength.getDbm();
331             int signalAsu = signalStrength.getAsuLevel();
332
333             if (-1 == signalDbm) {
334                 signalDbm = 0;
335             }
336
337             if (-1 == signalAsu) {
338                 signalAsu = 0;
339             }
340
341             mSignalStrength.setSummary(r.getString(R.string.sim_signal_strength,
342                         signalDbm, signalAsu));
343         }
344     }
345
346     private void updatePreference() {
347         if (mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) {
348             // only show area info when SIM country is Brazil
349             if (COUNTRY_ABBREVIATION_BRAZIL.equals(mTelephonyManager.getSimCountryIso(
350                             mSir.getSubscriptionId()))) {
351                 mShowLatestAreaInfo = true;
352             }
353         }
354
355         String rawNumber = mTelephonyManager.getLine1NumberForSubscriber(mSir.getSubscriptionId());
356         String formattedNumber = null;
357         if (!TextUtils.isEmpty(rawNumber)) {
358             formattedNumber = PhoneNumberUtils.formatNumber(rawNumber);
359         }
360         // If formattedNumber is null or empty, it'll display as "Unknown".
361         setSummaryText(KEY_PHONE_NUMBER, formattedNumber);
362
363         if (!mShowLatestAreaInfo) {
364             removePreferenceFromScreen(KEY_LATEST_AREA_INFO);
365         }
366     }
367
368     private void updatePhoneInfos() {
369         if (mSir != null) {
370             final Phone phone = PhoneFactory.getPhone(SubscriptionManager.getPhoneId(
371                         mSir.getSubscriptionId()));
372             if (UserHandle.myUserId() == UserHandle.USER_OWNER
373                     && SubscriptionManager.isValidSubscriptionId(mSir.getSubscriptionId())) {
374                 if (phone == null) {
375                     Log.e(TAG, "Unable to locate a phone object for the given Subscription ID.");
376                     return;
377                 }
378
379                 mPhone = phone;
380                 updateAreaInfo("");
381                 Intent getLatestIntent = new Intent(GET_LATEST_CB_AREA_INFO_ACTION);
382                 getLatestIntent.putExtra(PhoneConstants.SUBSCRIPTION_KEY,
383                         mSir.getSubscriptionId());
384                 sendBroadcastAsUser(getLatestIntent, UserHandle.ALL,
385                         CB_AREA_INFO_SENDER_PERMISSION);
386                 mPhoneStateListener = new PhoneStateListener(mSir.getSubscriptionId()) {
387                     @Override
388                     public void onDataConnectionStateChanged(int state) {
389                         updateDataState();
390                         updateNetworkType();
391                     }
392
393                     @Override
394                     public void onSignalStrengthsChanged(SignalStrength signalStrength) {
395                         updateSignalStrength(signalStrength);
396                     }
397
398                     @Override
399                     public void onServiceStateChanged(ServiceState serviceState) {
400                         updateServiceState(serviceState);
401                     }
402                 };
403             }
404         }
405     }
406 }