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