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