Home | History | Annotate | Download | only in about
      1 /*
      2  * Copyright (C) 2015 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.tv.settings.about;
     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.net.ConnectivityManager;
     25 import android.net.LinkProperties;
     26 import android.net.wifi.WifiInfo;
     27 import android.net.wifi.WifiManager;
     28 import android.os.Build;
     29 import android.os.Bundle;
     30 import android.os.Handler;
     31 import android.os.Message;
     32 import android.os.SystemClock;
     33 import android.os.SystemProperties;
     34 import android.os.UserManager;
     35 import android.support.annotation.Nullable;
     36 import android.support.v17.preference.LeanbackPreferenceFragment;
     37 import android.support.v7.preference.Preference;
     38 import android.text.TextUtils;
     39 import android.text.format.DateUtils;
     40 
     41 import com.android.internal.util.ArrayUtils;
     42 import com.android.tv.settings.R;
     43 
     44 import java.lang.ref.WeakReference;
     45 import java.net.InetAddress;
     46 import java.util.Iterator;
     47 
     48 public class StatusFragment extends LeanbackPreferenceFragment {
     49 
     50     private static final String KEY_BATTERY_STATUS = "battery_status";
     51     private static final String KEY_BATTERY_LEVEL = "battery_level";
     52     private static final String KEY_IP_ADDRESS = "wifi_ip_address";
     53     private static final String KEY_WIFI_MAC_ADDRESS = "wifi_mac_address";
     54     private static final String KEY_BT_ADDRESS = "bt_address";
     55     private static final String KEY_SERIAL_NUMBER = "serial_number";
     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 Preference mUptime;
     76     private Preference mBtAddress;
     77     private Preference mIpAddress;
     78     private Preference mWifiMacAddress;
     79     private Preference mWimaxMacAddress;
     80 
     81     private IntentFilter mConnectivityIntentFilter;
     82     private final BroadcastReceiver mConnectivityReceiver = new BroadcastReceiver() {
     83         @Override
     84         public void onReceive(Context context, Intent intent) {
     85             String action = intent.getAction();
     86             if (ArrayUtils.contains(CONNECTIVITY_INTENTS, action)) {
     87                 mHandler.sendEmptyMessage(EVENT_UPDATE_CONNECTIVITY);
     88             }
     89         }
     90     };
     91 
     92     private Handler mHandler;
     93 
     94     private static class MyHandler extends Handler {
     95         private WeakReference<StatusFragment> mStatus;
     96 
     97         public MyHandler(StatusFragment activity) {
     98             mStatus = new WeakReference<>(activity);
     99         }
    100 
    101         @Override
    102         public void handleMessage(Message msg) {
    103             StatusFragment status = mStatus.get();
    104             if (status == null) {
    105                 return;
    106             }
    107 
    108             switch (msg.what) {
    109                 case EVENT_UPDATE_STATS:
    110                     status.updateTimes();
    111                     sendEmptyMessageDelayed(EVENT_UPDATE_STATS, 1000);
    112                     break;
    113 
    114                 case EVENT_UPDATE_CONNECTIVITY:
    115                     status.updateConnectivity();
    116                     break;
    117             }
    118         }
    119     }
    120 
    121     public static StatusFragment newInstance() {
    122         return new StatusFragment();
    123     }
    124 
    125     @Override
    126     public void onCreate(Bundle savedInstanceState) {
    127         mHandler = new MyHandler(this);
    128 
    129         mCM = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
    130         mWifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE);
    131 
    132         super.onCreate(savedInstanceState);
    133     }
    134 
    135     @Override
    136     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    137         setPreferencesFromResource(R.xml.device_info_status, null);
    138 
    139         // TODO: detect if we have a battery or not
    140         removePreference(findPreference(KEY_BATTERY_LEVEL));
    141         removePreference(findPreference(KEY_BATTERY_STATUS));
    142         mBtAddress = findPreference(KEY_BT_ADDRESS);
    143         mWifiMacAddress = findPreference(KEY_WIFI_MAC_ADDRESS);
    144         mWimaxMacAddress = findPreference(KEY_WIMAX_MAC_ADDRESS);
    145         mIpAddress = findPreference(KEY_IP_ADDRESS);
    146         mUptime = findPreference("up_time");
    147 
    148         if (!hasBluetooth()) {
    149             getPreferenceScreen().removePreference(mBtAddress);
    150             mBtAddress = null;
    151         }
    152 
    153         if (!hasWimax()) {
    154             getPreferenceScreen().removePreference(mWimaxMacAddress);
    155             mWimaxMacAddress = null;
    156         }
    157 
    158         mConnectivityIntentFilter = new IntentFilter();
    159         for (String intent: CONNECTIVITY_INTENTS) {
    160             mConnectivityIntentFilter.addAction(intent);
    161         }
    162 
    163         updateConnectivity();
    164 
    165         final Preference serialPref = findPreference(KEY_SERIAL_NUMBER);
    166         String serial = Build.SERIAL;
    167         if (!TextUtils.isEmpty(serial)) {
    168             serialPref.setSummary(serial);
    169         } else {
    170             removePreference(serialPref);
    171         }
    172 
    173         // Remove SimStatus and Imei for Secondary user as it access Phone b/19165700
    174         // Also remove on Wi-Fi only devices.
    175         //TODO: the bug above will surface in split system user mode.
    176         if (!UserManager.get(getActivity()).isAdminUser()
    177                 || AboutFragment.isWifiOnly(getActivity())) {
    178             removePreference(findPreference(KEY_SIM_STATUS));
    179             removePreference(findPreference(KEY_IMEI_INFO));
    180         }
    181     }
    182 
    183     private void removePreference(@Nullable Preference preference) {
    184         if (preference != null) {
    185             getPreferenceScreen().removePreference(preference);
    186         }
    187     }
    188 
    189     private boolean hasBluetooth() {
    190         return BluetoothAdapter.getDefaultAdapter() != null;
    191     }
    192 
    193     private boolean hasWimax() {
    194         return  mCM.getNetworkInfo(ConnectivityManager.TYPE_WIMAX) != null;
    195     }
    196 
    197     @Override
    198     public void onStart() {
    199         super.onStart();
    200         getActivity().registerReceiver(mConnectivityReceiver, mConnectivityIntentFilter,
    201                 android.Manifest.permission.CHANGE_NETWORK_STATE, null);
    202         mHandler.sendEmptyMessage(EVENT_UPDATE_STATS);
    203     }
    204 
    205     @Override
    206     public void onStop() {
    207         super.onStop();
    208         getActivity().unregisterReceiver(mConnectivityReceiver);
    209         mHandler.removeMessages(EVENT_UPDATE_STATS);
    210     }
    211 
    212     private void setWimaxStatus() {
    213         if (mWimaxMacAddress != null) {
    214             String macAddress = SystemProperties.get("net.wimax.mac.address",
    215                     getString(R.string.status_unavailable));
    216             mWimaxMacAddress.setSummary(macAddress);
    217         }
    218     }
    219 
    220     private void setWifiStatus() {
    221         WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
    222         String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress();
    223         mWifiMacAddress.setSummary(!TextUtils.isEmpty(macAddress) ?
    224                 macAddress : getString(R.string.status_unavailable));
    225     }
    226 
    227     private void setIpAddressStatus() {
    228         String ipAddress = getDefaultIpAddresses(mCM);
    229         if (ipAddress != null) {
    230             mIpAddress.setSummary(ipAddress);
    231         } else {
    232             mIpAddress.setSummary(R.string.status_unavailable);
    233         }
    234     }
    235 
    236     private void setBtStatus() {
    237         BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
    238         if (bluetooth != null && mBtAddress != null) {
    239             String address = bluetooth.isEnabled() ? bluetooth.getAddress() : null;
    240             if (!TextUtils.isEmpty(address)) {
    241                 // Convert the address to lowercase for consistency with the wifi MAC address.
    242                 mBtAddress.setSummary(address.toLowerCase());
    243             } else {
    244                 mBtAddress.setSummary(R.string.status_unavailable);
    245             }
    246         }
    247     }
    248 
    249     void updateConnectivity() {
    250         setWimaxStatus();
    251         setWifiStatus();
    252         setBtStatus();
    253         setIpAddressStatus();
    254     }
    255 
    256     /**
    257      * Returns the default link's IP addresses, if any, taking into account IPv4 and IPv6 style
    258      * addresses.
    259      * @param cm ConnectivityManager
    260      * @return the formatted and newline-separated IP addresses, or null if none.
    261      */
    262     private static String getDefaultIpAddresses(ConnectivityManager cm) {
    263         LinkProperties prop = cm.getActiveLinkProperties();
    264         return formatIpAddresses(prop);
    265     }
    266 
    267     private static String formatIpAddresses(LinkProperties prop) {
    268         if (prop == null) return null;
    269         Iterator<InetAddress> iter = prop.getAllAddresses().iterator();
    270         // If there are no entries, return null
    271         if (!iter.hasNext()) return null;
    272         // Concatenate all available addresses, comma separated
    273         String addresses = "";
    274         while (iter.hasNext()) {
    275             addresses += iter.next().getHostAddress();
    276             if (iter.hasNext()) addresses += "\n";
    277         }
    278         return addresses;
    279     }
    280 
    281     void updateTimes() {
    282         mUptime.setSummary(DateUtils.formatDuration(SystemClock.elapsedRealtime()));
    283     }
    284 
    285 }
    286