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