Home | History | Annotate | Download | only in wifi
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
      5  *
      6  *      http://www.apache.org/licenses/LICENSE-2.0
      7  *
      8  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
      9  */
     10 
     11 package com.android.settingslib.wifi;
     12 
     13 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
     14 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
     15 
     16 import android.content.Context;
     17 import android.content.Intent;
     18 import android.net.ConnectivityManager;
     19 import android.net.Network;
     20 import android.net.NetworkCapabilities;
     21 import android.net.NetworkInfo;
     22 import android.net.NetworkKey;
     23 import android.net.NetworkRequest;
     24 import android.net.NetworkScoreManager;
     25 import android.net.ScoredNetwork;
     26 import android.net.wifi.WifiConfiguration;
     27 import android.net.wifi.WifiInfo;
     28 import android.net.wifi.WifiManager;
     29 import android.net.wifi.WifiNetworkScoreCache;
     30 import android.net.wifi.WifiSsid;
     31 import android.os.Handler;
     32 import android.os.Looper;
     33 
     34 import com.android.settingslib.R;
     35 
     36 import java.util.List;
     37 
     38 public class WifiStatusTracker extends ConnectivityManager.NetworkCallback {
     39     private final Context mContext;
     40     private final WifiNetworkScoreCache mWifiNetworkScoreCache;
     41     private final WifiManager mWifiManager;
     42     private final NetworkScoreManager mNetworkScoreManager;
     43     private final ConnectivityManager mConnectivityManager;
     44     private final Handler mHandler = new Handler(Looper.getMainLooper());
     45     private final WifiNetworkScoreCache.CacheListener mCacheListener =
     46             new WifiNetworkScoreCache.CacheListener(mHandler) {
     47                 @Override
     48                 public void networkCacheUpdated(List<ScoredNetwork> updatedNetworks) {
     49                     updateStatusLabel();
     50                     mCallback.run();
     51                 }
     52             };
     53     private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
     54             .clearCapabilities()
     55             .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
     56             .addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build();
     57     private final ConnectivityManager.NetworkCallback mNetworkCallback = new ConnectivityManager
     58             .NetworkCallback() {
     59         @Override
     60         public void onCapabilitiesChanged(
     61                 Network network, NetworkCapabilities networkCapabilities) {
     62             updateStatusLabel();
     63             mCallback.run();
     64         }
     65     };
     66     private final Runnable mCallback;
     67 
     68     private WifiInfo mWifiInfo;
     69     public boolean enabled;
     70     public int state;
     71     public boolean connected;
     72     public String ssid;
     73     public int rssi;
     74     public int level;
     75     public String statusLabel;
     76 
     77     public WifiStatusTracker(Context context, WifiManager wifiManager,
     78             NetworkScoreManager networkScoreManager, ConnectivityManager connectivityManager,
     79             Runnable callback) {
     80         mContext = context;
     81         mWifiManager = wifiManager;
     82         mWifiNetworkScoreCache = new WifiNetworkScoreCache(context);
     83         mNetworkScoreManager = networkScoreManager;
     84         mConnectivityManager = connectivityManager;
     85         mCallback = callback;
     86     }
     87 
     88     public void setListening(boolean listening) {
     89         if (listening) {
     90             mNetworkScoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
     91                     mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
     92             mWifiNetworkScoreCache.registerListener(mCacheListener);
     93             mConnectivityManager.registerNetworkCallback(
     94                     mNetworkRequest, mNetworkCallback, mHandler);
     95         } else {
     96             mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI,
     97                     mWifiNetworkScoreCache);
     98             mWifiNetworkScoreCache.unregisterListener();
     99             mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
    100         }
    101     }
    102 
    103     public void handleBroadcast(Intent intent) {
    104         String action = intent.getAction();
    105         if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
    106             updateWifiState();
    107         } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    108             updateWifiState();
    109             final NetworkInfo networkInfo =
    110                     intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    111             connected = networkInfo != null && networkInfo.isConnected();
    112             mWifiInfo = null;
    113             ssid = null;
    114             if (connected) {
    115                 mWifiInfo = mWifiManager.getConnectionInfo();
    116                 if (mWifiInfo != null) {
    117                     ssid = getValidSsid(mWifiInfo);
    118                     updateRssi(mWifiInfo.getRssi());
    119                     maybeRequestNetworkScore();
    120                 }
    121             }
    122             updateStatusLabel();
    123         } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
    124             // Default to -200 as its below WifiManager.MIN_RSSI.
    125             updateRssi(intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200));
    126             updateStatusLabel();
    127         }
    128     }
    129 
    130     private void updateWifiState() {
    131         state = mWifiManager.getWifiState();
    132         enabled = state == WifiManager.WIFI_STATE_ENABLED;
    133     }
    134 
    135     private void updateRssi(int newRssi) {
    136         rssi = newRssi;
    137         level = WifiManager.calculateSignalLevel(rssi, WifiManager.RSSI_LEVELS);
    138     }
    139 
    140     private void maybeRequestNetworkScore() {
    141         NetworkKey networkKey = NetworkKey.createFromWifiInfo(mWifiInfo);
    142         if (mWifiNetworkScoreCache.getScoredNetwork(networkKey) == null) {
    143             mNetworkScoreManager.requestScores(new NetworkKey[]{ networkKey });
    144         }
    145     }
    146 
    147     private void updateStatusLabel() {
    148         final NetworkCapabilities networkCapabilities
    149                 = mConnectivityManager.getNetworkCapabilities(mWifiManager.getCurrentNetwork());
    150         if (networkCapabilities != null) {
    151             if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) {
    152                 statusLabel = mContext.getString(R.string.wifi_status_sign_in_required);
    153                 return;
    154             } else if (!networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
    155                 statusLabel = mContext.getString(R.string.wifi_status_no_internet);
    156                 return;
    157             }
    158         }
    159 
    160         ScoredNetwork scoredNetwork =
    161                 mWifiNetworkScoreCache.getScoredNetwork(NetworkKey.createFromWifiInfo(mWifiInfo));
    162         statusLabel = scoredNetwork == null
    163                 ? null : AccessPoint.getSpeedLabel(mContext, scoredNetwork, rssi);
    164     }
    165 
    166     private String getValidSsid(WifiInfo info) {
    167         String ssid = info.getSSID();
    168         if (ssid != null && !WifiSsid.NONE.equals(ssid)) {
    169             return ssid;
    170         }
    171         // OK, it's not in the connectionInfo; we have to go hunting for it
    172         List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
    173         int length = networks.size();
    174         for (int i = 0; i < length; i++) {
    175             if (networks.get(i).networkId == info.getNetworkId()) {
    176                 return networks.get(i).SSID;
    177             }
    178         }
    179         return null;
    180     }
    181 }
    182