Status.java revision b7e4380cd27ffd8a060ecb61201057fb6843e408
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 static android.content.Context.CONNECTIVITY_SERVICE;
20import static android.content.Context.WIFI_SERVICE;
21
22import android.bluetooth.BluetoothAdapter;
23import android.content.BroadcastReceiver;
24import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
27import android.content.res.Resources;
28import android.net.ConnectivityManager;
29import android.net.wifi.WifiInfo;
30import android.net.wifi.WifiManager;
31import android.os.Build;
32import android.os.Bundle;
33import android.os.Handler;
34import android.os.Message;
35import android.os.SystemClock;
36import android.os.SystemProperties;
37import android.os.UserManager;
38import android.support.v7.preference.Preference;
39import android.text.TextUtils;
40
41import com.android.internal.logging.MetricsProto.MetricsEvent;
42import com.android.internal.util.ArrayUtils;
43import com.android.settings.R;
44import com.android.settings.SettingsPreferenceFragment;
45import com.android.settings.Utils;
46
47import java.lang.ref.WeakReference;
48
49/**
50 * Display the following information
51 * # Battery Strength  : TODO
52 * # Uptime
53 * # Awake Time
54 * # XMPP/buzz/tickle status : TODO
55 *
56 */
57public class Status extends SettingsPreferenceFragment {
58
59    private static final String KEY_BATTERY_STATUS = "battery_status";
60    private static final String KEY_BATTERY_LEVEL = "battery_level";
61    private static final String KEY_IP_ADDRESS = "wifi_ip_address";
62    private static final String KEY_WIFI_MAC_ADDRESS = "wifi_mac_address";
63    private static final String KEY_BT_ADDRESS = "bt_address";
64    private static final String KEY_SERIAL_NUMBER = "serial_number";
65    private static final String KEY_WIMAX_MAC_ADDRESS = "wimax_mac_address";
66    private static final String KEY_SIM_STATUS = "sim_status";
67    private static final String KEY_IMEI_INFO = "imei_info";
68
69    // Broadcasts to listen to for connectivity changes.
70    private static final String[] CONNECTIVITY_INTENTS = {
71            BluetoothAdapter.ACTION_STATE_CHANGED,
72            ConnectivityManager.CONNECTIVITY_ACTION,
73            WifiManager.LINK_CONFIGURATION_CHANGED_ACTION,
74            WifiManager.NETWORK_STATE_CHANGED_ACTION,
75    };
76
77    private static final int EVENT_UPDATE_STATS = 500;
78
79    private static final int EVENT_UPDATE_CONNECTIVITY = 600;
80
81    private ConnectivityManager mCM;
82    private WifiManager mWifiManager;
83
84    private Resources mRes;
85
86    private String mUnknown;
87    private String mUnavailable;
88
89    private Preference mUptime;
90    private Preference mBatteryStatus;
91    private Preference mBatteryLevel;
92    private Preference mBtAddress;
93    private Preference mIpAddress;
94    private Preference mWifiMacAddress;
95    private Preference mWimaxMacAddress;
96
97    private Handler mHandler;
98
99    private static class MyHandler extends Handler {
100        private WeakReference<Status> mStatus;
101
102        public MyHandler(Status activity) {
103            mStatus = new WeakReference<Status>(activity);
104        }
105
106        @Override
107        public void handleMessage(Message msg) {
108            Status status = mStatus.get();
109            if (status == null) {
110                return;
111            }
112
113            switch (msg.what) {
114                case EVENT_UPDATE_STATS:
115                    status.updateTimes();
116                    sendEmptyMessageDelayed(EVENT_UPDATE_STATS, 1000);
117                    break;
118
119                case EVENT_UPDATE_CONNECTIVITY:
120                    status.updateConnectivity();
121                    break;
122            }
123        }
124    }
125
126    private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
127
128        @Override
129        public void onReceive(Context context, Intent intent) {
130            String action = intent.getAction();
131            if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
132                mBatteryLevel.setSummary(Utils.getBatteryPercentage(intent));
133                mBatteryStatus.setSummary(Utils.getBatteryStatus(getResources(), intent));
134            }
135        }
136    };
137
138    private IntentFilter mConnectivityIntentFilter;
139    private final BroadcastReceiver mConnectivityReceiver = new BroadcastReceiver() {
140        @Override
141        public void onReceive(Context context, Intent intent) {
142            String action = intent.getAction();
143            if (ArrayUtils.contains(CONNECTIVITY_INTENTS, action)) {
144                mHandler.sendEmptyMessage(EVENT_UPDATE_CONNECTIVITY);
145            }
146        }
147    };
148
149    private boolean hasBluetooth() {
150        return BluetoothAdapter.getDefaultAdapter() != null;
151    }
152
153    private boolean hasWimax() {
154        return  mCM.getNetworkInfo(ConnectivityManager.TYPE_WIMAX) != null;
155    }
156
157    @Override
158    public void onCreate(Bundle icicle) {
159        super.onCreate(icicle);
160
161        mHandler = new MyHandler(this);
162
163        mCM = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
164        mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
165
166        addPreferencesFromResource(R.xml.device_info_status);
167        mBatteryLevel = findPreference(KEY_BATTERY_LEVEL);
168        mBatteryStatus = findPreference(KEY_BATTERY_STATUS);
169        mBtAddress = findPreference(KEY_BT_ADDRESS);
170        mWifiMacAddress = findPreference(KEY_WIFI_MAC_ADDRESS);
171        mWimaxMacAddress = findPreference(KEY_WIMAX_MAC_ADDRESS);
172        mIpAddress = findPreference(KEY_IP_ADDRESS);
173
174        mRes = getResources();
175        mUnknown = mRes.getString(R.string.device_info_default);
176        mUnavailable = mRes.getString(R.string.status_unavailable);
177
178        // Note - missing in zaku build, be careful later...
179        mUptime = findPreference("up_time");
180
181        if (!hasBluetooth()) {
182            getPreferenceScreen().removePreference(mBtAddress);
183            mBtAddress = null;
184        }
185
186        if (!hasWimax()) {
187            getPreferenceScreen().removePreference(mWimaxMacAddress);
188            mWimaxMacAddress = null;
189        }
190
191        mConnectivityIntentFilter = new IntentFilter();
192        for (String intent: CONNECTIVITY_INTENTS) {
193             mConnectivityIntentFilter.addAction(intent);
194        }
195
196        updateConnectivity();
197
198        String serial = Build.SERIAL;
199        if (serial != null && !serial.equals("")) {
200            setSummaryText(KEY_SERIAL_NUMBER, serial);
201        } else {
202            removePreferenceFromScreen(KEY_SERIAL_NUMBER);
203        }
204
205        // Remove SimStatus and Imei for Secondary user as it access Phone b/19165700
206        // Also remove on Wi-Fi only devices.
207        //TODO: the bug above will surface in split system user mode.
208        if (!UserManager.get(getContext()).isAdminUser()
209                || Utils.isWifiOnly(getContext())) {
210            removePreferenceFromScreen(KEY_SIM_STATUS);
211            removePreferenceFromScreen(KEY_IMEI_INFO);
212        }
213    }
214
215    @Override
216    protected int getMetricsCategory() {
217        return MetricsEvent.DEVICEINFO_STATUS;
218    }
219
220    @Override
221    public void onResume() {
222        super.onResume();
223        getContext().registerReceiver(mConnectivityReceiver, mConnectivityIntentFilter,
224                         android.Manifest.permission.CHANGE_NETWORK_STATE, null);
225        getContext().registerReceiver(mBatteryInfoReceiver,
226                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
227        mHandler.sendEmptyMessage(EVENT_UPDATE_STATS);
228    }
229
230    @Override
231    public void onPause() {
232        super.onPause();
233
234        getContext().unregisterReceiver(mBatteryInfoReceiver);
235        getContext().unregisterReceiver(mConnectivityReceiver);
236        mHandler.removeMessages(EVENT_UPDATE_STATS);
237    }
238
239    /**
240     * Removes the specified preference, if it exists.
241     * @param key the key for the Preference item
242     */
243    private void removePreferenceFromScreen(String key) {
244        Preference pref = findPreference(key);
245        if (pref != null) {
246            getPreferenceScreen().removePreference(pref);
247        }
248    }
249
250    /**
251     * @param preference The key for the Preference item
252     * @param property The system property to fetch
253     * @param alt The default value, if the property doesn't exist
254     */
255    private void setSummary(String preference, String property, String alt) {
256        try {
257            findPreference(preference).setSummary(
258                    SystemProperties.get(property, alt));
259        } catch (RuntimeException e) {
260
261        }
262    }
263
264    private void setSummaryText(String preference, String text) {
265            if (TextUtils.isEmpty(text)) {
266               text = mUnknown;
267             }
268             // some preferences may be missing
269             if (findPreference(preference) != null) {
270                 findPreference(preference).setSummary(text);
271             }
272    }
273
274    private void setWimaxStatus() {
275        if (mWimaxMacAddress != null) {
276            String macAddress = SystemProperties.get("net.wimax.mac.address", mUnavailable);
277            mWimaxMacAddress.setSummary(macAddress);
278        }
279    }
280
281    private void setWifiStatus() {
282        WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
283        String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress();
284        mWifiMacAddress.setSummary(!TextUtils.isEmpty(macAddress) ? macAddress : mUnavailable);
285    }
286
287    private void setIpAddressStatus() {
288        String ipAddress = Utils.getDefaultIpAddresses(this.mCM);
289        if (ipAddress != null) {
290            mIpAddress.setSummary(ipAddress);
291        } else {
292            mIpAddress.setSummary(mUnavailable);
293        }
294    }
295
296    private void setBtStatus() {
297        BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
298        if (bluetooth != null && mBtAddress != null) {
299            String address = bluetooth.isEnabled() ? bluetooth.getAddress() : null;
300            if (!TextUtils.isEmpty(address)) {
301               // Convert the address to lowercase for consistency with the wifi MAC address.
302                mBtAddress.setSummary(address.toLowerCase());
303            } else {
304                mBtAddress.setSummary(mUnavailable);
305            }
306        }
307    }
308
309    void updateConnectivity() {
310        setWimaxStatus();
311        setWifiStatus();
312        setBtStatus();
313        setIpAddressStatus();
314    }
315
316    void updateTimes() {
317        long at = SystemClock.uptimeMillis() / 1000;
318        long ut = SystemClock.elapsedRealtime() / 1000;
319
320        if (ut == 0) {
321            ut = 1;
322        }
323
324        mUptime.setSummary(convert(ut));
325    }
326
327    private String pad(int n) {
328        if (n >= 10) {
329            return String.valueOf(n);
330        } else {
331            return "0" + String.valueOf(n);
332        }
333    }
334
335    private String convert(long t) {
336        int s = (int)(t % 60);
337        int m = (int)((t / 60) % 60);
338        int h = (int)((t / 3600));
339
340        return h + ":" + pad(m) + ":" + pad(s);
341    }
342}
343