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