Status.java revision 7c5c16565eccde0b98f7ad08a0f06ff51e8e90ce
1/*
2 * Copyright (C) 2008 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
17package com.android.settings.deviceinfo;
18
19import android.bluetooth.BluetoothAdapter;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.content.res.Resources;
25import android.net.ConnectivityManager;
26import android.net.NetworkInfo;
27import android.net.wifi.WifiInfo;
28import android.net.wifi.WifiManager;
29import android.os.BatteryManager;
30import android.os.Build;
31import android.os.Bundle;
32import android.os.Handler;
33import android.os.Message;
34import android.os.SystemClock;
35import android.os.SystemProperties;
36import android.preference.Preference;
37import android.preference.PreferenceActivity;
38import android.preference.PreferenceScreen;
39import android.telephony.PhoneNumberUtils;
40import android.telephony.PhoneStateListener;
41import android.telephony.ServiceState;
42import android.telephony.TelephonyManager;
43import android.text.TextUtils;
44
45import com.android.internal.telephony.Phone;
46import com.android.internal.telephony.PhoneFactory;
47import com.android.internal.telephony.PhoneStateIntentReceiver;
48import com.android.internal.telephony.TelephonyProperties;
49import com.android.settings.R;
50import com.android.settings.Utils;
51
52import java.lang.ref.WeakReference;
53
54/**
55 * Display the following information
56 * # Phone Number
57 * # Network
58 * # Roaming
59 * # Device Id (IMEI in GSM and MEID in CDMA)
60 * # Network type
61 * # Signal Strength
62 * # Battery Strength  : TODO
63 * # Uptime
64 * # Awake Time
65 * # XMPP/buzz/tickle status : TODO
66 *
67 */
68public class Status extends PreferenceActivity {
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_PHONE_NUMBER = "number";
76    private static final String KEY_IMEI_SV = "imei_sv";
77    private static final String KEY_IMEI = "imei";
78    private static final String KEY_PRL_VERSION = "prl_version";
79    private static final String KEY_MIN_NUMBER = "min_number";
80    private static final String KEY_MEID_NUMBER = "meid_number";
81    private static final String KEY_SIGNAL_STRENGTH = "signal_strength";
82    private static final String KEY_BATTERY_STATUS = "battery_status";
83    private static final String KEY_BATTERY_LEVEL = "battery_level";
84    private static final String KEY_IP_ADDRESS = "wifi_ip_address";
85    private static final String KEY_WIFI_MAC_ADDRESS = "wifi_mac_address";
86    private static final String KEY_BT_ADDRESS = "bt_address";
87    private static final String KEY_SERIAL_NUMBER = "serial_number";
88    private static final String KEY_ICC_ID = "icc_id";
89    private static final String KEY_WIMAX_MAC_ADDRESS = "wimax_mac_address";
90    private static final String[] PHONE_RELATED_ENTRIES = {
91        KEY_DATA_STATE,
92        KEY_SERVICE_STATE,
93        KEY_OPERATOR_NAME,
94        KEY_ROAMING_STATE,
95        KEY_NETWORK_TYPE,
96        KEY_PHONE_NUMBER,
97        KEY_IMEI,
98        KEY_IMEI_SV,
99        KEY_PRL_VERSION,
100        KEY_MIN_NUMBER,
101        KEY_MEID_NUMBER,
102        KEY_SIGNAL_STRENGTH,
103        KEY_ICC_ID
104    };
105
106    private static final int EVENT_SIGNAL_STRENGTH_CHANGED = 200;
107    private static final int EVENT_SERVICE_STATE_CHANGED = 300;
108
109    private static final int EVENT_UPDATE_STATS = 500;
110
111    private TelephonyManager mTelephonyManager;
112    private Phone mPhone = null;
113    private PhoneStateIntentReceiver mPhoneStateReceiver;
114    private Resources mRes;
115    private Preference mSignalStrength;
116    private Preference mUptime;
117
118    private static String sUnknown;
119
120    private Preference mBatteryStatus;
121    private Preference mBatteryLevel;
122
123    private Handler mHandler;
124
125    private static class MyHandler extends Handler {
126        private WeakReference<Status> mStatus;
127
128        public MyHandler(Status activity) {
129            mStatus = new WeakReference<Status>(activity);
130        }
131
132        @Override
133        public void handleMessage(Message msg) {
134            Status status = mStatus.get();
135            if (status == null) {
136                return;
137            }
138
139            switch (msg.what) {
140                case EVENT_SIGNAL_STRENGTH_CHANGED:
141                    status.updateSignalStrength();
142                    break;
143
144                case EVENT_SERVICE_STATE_CHANGED:
145                    ServiceState serviceState = status.mPhoneStateReceiver.getServiceState();
146                    status.updateServiceState(serviceState);
147                    break;
148
149                case EVENT_UPDATE_STATS:
150                    status.updateTimes();
151                    sendEmptyMessageDelayed(EVENT_UPDATE_STATS, 1000);
152                    break;
153            }
154        }
155    }
156
157    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
158
159        @Override
160        public void onReceive(Context context, Intent intent) {
161            String action = intent.getAction();
162            if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
163                mBatteryLevel.setSummary(Utils.getBatteryPercentage(intent));
164                mBatteryStatus.setSummary(Utils.getBatteryStatus(getResources(), intent));
165            }
166        }
167    };
168
169    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
170        @Override
171        public void onDataConnectionStateChanged(int state) {
172            updateDataState();
173            updateNetworkType();
174        }
175    };
176
177    @Override
178    protected void onCreate(Bundle icicle) {
179        super.onCreate(icicle);
180        Preference removablePref;
181
182        mHandler = new MyHandler(this);
183
184        mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
185
186        addPreferencesFromResource(R.xml.device_info_status);
187        mBatteryLevel = findPreference(KEY_BATTERY_LEVEL);
188        mBatteryStatus = findPreference(KEY_BATTERY_STATUS);
189
190        mRes = getResources();
191        if (sUnknown == null) {
192            sUnknown = mRes.getString(R.string.device_info_default);
193        }
194
195        mPhone = PhoneFactory.getDefaultPhone();
196        // Note - missing in zaku build, be careful later...
197        mSignalStrength = findPreference(KEY_SIGNAL_STRENGTH);
198        mUptime = findPreference("up_time");
199
200        if (Utils.isWifiOnly(getApplicationContext())) {
201            for (String key : PHONE_RELATED_ENTRIES) {
202                removePreferenceFromScreen(key);
203            }
204        } else {
205            // NOTE "imei" is the "Device ID" since it represents
206            //  the IMEI in GSM and the MEID in CDMA
207            if (mPhone.getPhoneName().equals("CDMA")) {
208                setSummaryText(KEY_MEID_NUMBER, mPhone.getMeid());
209                setSummaryText(KEY_MIN_NUMBER, mPhone.getCdmaMin());
210                if (getResources().getBoolean(R.bool.config_msid_enable)) {
211                    findPreference(KEY_MIN_NUMBER).setTitle(R.string.status_msid_number);
212                }
213                setSummaryText(KEY_PRL_VERSION, mPhone.getCdmaPrlVersion());
214                removePreferenceFromScreen(KEY_IMEI_SV);
215
216                if (mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
217                    // Show ICC ID and IMEI for LTE device
218                    setSummaryText(KEY_ICC_ID, mPhone.getIccSerialNumber());
219                    setSummaryText(KEY_IMEI, mPhone.getImei());
220                } else {
221                    // device is not GSM/UMTS, do not display GSM/UMTS features
222                    // check Null in case no specified preference in overlay xml
223                    removePreferenceFromScreen(KEY_IMEI);
224                    removePreferenceFromScreen(KEY_ICC_ID);
225                }
226            } else {
227                setSummaryText(KEY_IMEI, mPhone.getDeviceId());
228
229                setSummaryText(KEY_IMEI_SV,
230                        ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
231                            .getDeviceSoftwareVersion());
232
233                // device is not CDMA, do not display CDMA features
234                // check Null in case no specified preference in overlay xml
235                removePreferenceFromScreen(KEY_PRL_VERSION);
236                removePreferenceFromScreen(KEY_MEID_NUMBER);
237                removePreferenceFromScreen(KEY_MIN_NUMBER);
238                removePreferenceFromScreen(KEY_ICC_ID);
239            }
240
241            String rawNumber = mPhone.getLine1Number();  // may be null or empty
242            String formattedNumber = null;
243            if (!TextUtils.isEmpty(rawNumber)) {
244                formattedNumber = PhoneNumberUtils.formatNumber(rawNumber);
245            }
246            // If formattedNumber is null or empty, it'll display as "Unknown".
247            setSummaryText(KEY_PHONE_NUMBER, formattedNumber);
248
249            mPhoneStateReceiver = new PhoneStateIntentReceiver(this, mHandler);
250            mPhoneStateReceiver.notifySignalStrength(EVENT_SIGNAL_STRENGTH_CHANGED);
251            mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED);
252        }
253
254        setWimaxStatus();
255        setWifiStatus();
256        setBtStatus();
257        setIpAddressStatus();
258
259        String serial = Build.SERIAL;
260        if (serial != null && !serial.equals("")) {
261            setSummaryText(KEY_SERIAL_NUMBER, serial);
262        } else {
263            removePreferenceFromScreen(KEY_SERIAL_NUMBER);
264        }
265    }
266
267    @Override
268    protected void onResume() {
269        super.onResume();
270
271        if (!Utils.isWifiOnly(getApplicationContext())) {
272            mPhoneStateReceiver.registerIntent();
273
274            updateSignalStrength();
275            updateServiceState(mPhone.getServiceState());
276            updateDataState();
277
278            mTelephonyManager.listen(mPhoneStateListener,
279                      PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
280        }
281        registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
282        mHandler.sendEmptyMessage(EVENT_UPDATE_STATS);
283    }
284
285    @Override
286    public void onPause() {
287        super.onPause();
288
289        if (!Utils.isWifiOnly(getApplicationContext())) {
290            mPhoneStateReceiver.unregisterIntent();
291            mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
292        }
293        unregisterReceiver(mBatteryInfoReceiver);
294        mHandler.removeMessages(EVENT_UPDATE_STATS);
295    }
296
297    /**
298     * Removes the specified preference, if it exists.
299     * @param key the key for the Preference item
300     */
301    private void removePreferenceFromScreen(String key) {
302        Preference pref = findPreference(key);
303        if (pref != null) {
304            getPreferenceScreen().removePreference(pref);
305        }
306    }
307
308    /**
309     * @param preference The key for the Preference item
310     * @param property The system property to fetch
311     * @param alt The default value, if the property doesn't exist
312     */
313    private void setSummary(String preference, String property, String alt) {
314        try {
315            findPreference(preference).setSummary(
316                    SystemProperties.get(property, alt));
317        } catch (RuntimeException e) {
318
319        }
320    }
321
322    private void setSummaryText(String preference, String text) {
323            if (TextUtils.isEmpty(text)) {
324               text = sUnknown;
325             }
326             // some preferences may be missing
327             if (findPreference(preference) != null) {
328                 findPreference(preference).setSummary(text);
329             }
330    }
331
332    private void updateNetworkType() {
333        // Whether EDGE, UMTS, etc...
334        setSummary(KEY_NETWORK_TYPE, TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE, sUnknown);
335    }
336
337    private void updateDataState() {
338        int state = mTelephonyManager.getDataState();
339        String display = mRes.getString(R.string.radioInfo_unknown);
340
341        switch (state) {
342            case TelephonyManager.DATA_CONNECTED:
343                display = mRes.getString(R.string.radioInfo_data_connected);
344                break;
345            case TelephonyManager.DATA_SUSPENDED:
346                display = mRes.getString(R.string.radioInfo_data_suspended);
347                break;
348            case TelephonyManager.DATA_CONNECTING:
349                display = mRes.getString(R.string.radioInfo_data_connecting);
350                break;
351            case TelephonyManager.DATA_DISCONNECTED:
352                display = mRes.getString(R.string.radioInfo_data_disconnected);
353                break;
354        }
355
356        setSummaryText(KEY_DATA_STATE, display);
357    }
358
359    private void updateServiceState(ServiceState serviceState) {
360        int state = serviceState.getState();
361        String display = mRes.getString(R.string.radioInfo_unknown);
362
363        switch (state) {
364            case ServiceState.STATE_IN_SERVICE:
365                display = mRes.getString(R.string.radioInfo_service_in);
366                break;
367            case ServiceState.STATE_OUT_OF_SERVICE:
368            case ServiceState.STATE_EMERGENCY_ONLY:
369                display = mRes.getString(R.string.radioInfo_service_out);
370                break;
371            case ServiceState.STATE_POWER_OFF:
372                display = mRes.getString(R.string.radioInfo_service_off);
373                break;
374        }
375
376        setSummaryText(KEY_SERVICE_STATE, display);
377
378        if (serviceState.getRoaming()) {
379            setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_in));
380        } else {
381            setSummaryText(KEY_ROAMING_STATE, mRes.getString(R.string.radioInfo_roaming_not));
382        }
383        setSummaryText(KEY_OPERATOR_NAME, serviceState.getOperatorAlphaLong());
384    }
385
386    void updateSignalStrength() {
387        // TODO PhoneStateIntentReceiver is deprecated and PhoneStateListener
388        // should probably used instead.
389
390        // not loaded in some versions of the code (e.g., zaku)
391        if (mSignalStrength != null) {
392            int state =
393                    mPhoneStateReceiver.getServiceState().getState();
394            Resources r = getResources();
395
396            if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
397                    (ServiceState.STATE_POWER_OFF == state)) {
398                mSignalStrength.setSummary("0");
399            }
400
401            int signalDbm = mPhoneStateReceiver.getSignalStrengthDbm();
402
403            if (-1 == signalDbm) signalDbm = 0;
404
405            int signalAsu = mPhoneStateReceiver.getSignalStrengthLevelAsu();
406
407            if (-1 == signalAsu) signalAsu = 0;
408
409            mSignalStrength.setSummary(String.valueOf(signalDbm) + " "
410                        + r.getString(R.string.radioInfo_display_dbm) + "   "
411                        + String.valueOf(signalAsu) + " "
412                        + r.getString(R.string.radioInfo_display_asu));
413        }
414    }
415
416    private void setWimaxStatus() {
417        ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
418        NetworkInfo ni = cm.getNetworkInfo(ConnectivityManager.TYPE_WIMAX);
419
420        if (ni == null) {
421            PreferenceScreen root = getPreferenceScreen();
422            Preference ps = (Preference) findPreference(KEY_WIMAX_MAC_ADDRESS);
423            if (ps != null) root.removePreference(ps);
424        } else {
425            Preference wimaxMacAddressPref = findPreference(KEY_WIMAX_MAC_ADDRESS);
426            String macAddress = SystemProperties.get("net.wimax.mac.address",
427                    getString(R.string.status_unavailable));
428            wimaxMacAddressPref.setSummary(macAddress);
429        }
430    }
431    private void setWifiStatus() {
432        WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
433        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
434
435        Preference wifiMacAddressPref = findPreference(KEY_WIFI_MAC_ADDRESS);
436
437        String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress();
438        wifiMacAddressPref.setSummary(!TextUtils.isEmpty(macAddress) ? macAddress
439                : getString(R.string.status_unavailable));
440    }
441
442    private void setIpAddressStatus() {
443        Preference ipAddressPref = findPreference(KEY_IP_ADDRESS);
444        String ipAddress = Utils.getDefaultIpAddresses(this);
445        if (ipAddress != null) {
446            ipAddressPref.setSummary(ipAddress);
447        } else {
448            ipAddressPref.setSummary(getString(R.string.status_unavailable));
449        }
450    }
451
452    private void setBtStatus() {
453        BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
454        Preference btAddressPref = findPreference(KEY_BT_ADDRESS);
455
456        if (bluetooth == null) {
457            // device not BT capable
458            getPreferenceScreen().removePreference(btAddressPref);
459        } else {
460            String address = bluetooth.isEnabled() ? bluetooth.getAddress() : null;
461            btAddressPref.setSummary(!TextUtils.isEmpty(address) ? address
462                    : getString(R.string.status_unavailable));
463        }
464    }
465
466    void updateTimes() {
467        long at = SystemClock.uptimeMillis() / 1000;
468        long ut = SystemClock.elapsedRealtime() / 1000;
469
470        if (ut == 0) {
471            ut = 1;
472        }
473
474        mUptime.setSummary(convert(ut));
475    }
476
477    private String pad(int n) {
478        if (n >= 10) {
479            return String.valueOf(n);
480        } else {
481            return "0" + String.valueOf(n);
482        }
483    }
484
485    private String convert(long t) {
486        int s = (int)(t % 60);
487        int m = (int)((t / 60) % 60);
488        int h = (int)((t / 3600));
489
490        return h + ":" + pad(m) + ":" + pad(s);
491    }
492}
493