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_PARTIAL_CONNECTIVITY;
     15 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
     16 
     17 import android.content.Context;
     18 import android.content.Intent;
     19 import android.net.ConnectivityManager;
     20 import android.net.Network;
     21 import android.net.NetworkCapabilities;
     22 import android.net.NetworkInfo;
     23 import android.net.NetworkKey;
     24 import android.net.NetworkRequest;
     25 import android.net.NetworkScoreManager;
     26 import android.net.ScoredNetwork;
     27 import android.net.wifi.WifiConfiguration;
     28 import android.net.wifi.WifiInfo;
     29 import android.net.wifi.WifiManager;
     30 import android.net.wifi.WifiNetworkScoreCache;
     31 import android.net.wifi.WifiSsid;
     32 import android.os.Handler;
     33 import android.os.Looper;
     34 
     35 import com.android.settingslib.R;
     36 
     37 import java.util.List;
     38 
     39 public class WifiStatusTracker extends ConnectivityManager.NetworkCallback {
     40     private final Context mContext;
     41     private final WifiNetworkScoreCache mWifiNetworkScoreCache;
     42     private final WifiManager mWifiManager;
     43     private final NetworkScoreManager mNetworkScoreManager;
     44     private final ConnectivityManager mConnectivityManager;
     45     private final Handler mHandler = new Handler(Looper.getMainLooper());
     46     private final WifiNetworkScoreCache.CacheListener mCacheListener =
     47             new WifiNetworkScoreCache.CacheListener(mHandler) {
     48                 @Override
     49                 public void networkCacheUpdated(List<ScoredNetwork> updatedNetworks) {
     50                     updateStatusLabel();
     51                     mCallback.run();
     52                 }
     53             };
     54     private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
     55             .clearCapabilities()
     56             .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
     57             .addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build();
     58     private final ConnectivityManager.NetworkCallback mNetworkCallback = new ConnectivityManager
     59             .NetworkCallback() {
     60         @Override
     61         public void onCapabilitiesChanged(
     62                 Network network, NetworkCapabilities networkCapabilities) {
     63             updateStatusLabel();
     64             mCallback.run();
     65         }
     66     };
     67     private final Runnable mCallback;
     68 
     69     private WifiInfo mWifiInfo;
     70     public boolean enabled;
     71     public int state;
     72     public boolean connected;
     73     public String ssid;
     74     public int rssi;
     75     public int level;
     76     public String statusLabel;
     77 
     78     public WifiStatusTracker(Context context, WifiManager wifiManager,
     79             NetworkScoreManager networkScoreManager, ConnectivityManager connectivityManager,
     80             Runnable callback) {
     81         mContext = context;
     82         mWifiManager = wifiManager;
     83         mWifiNetworkScoreCache = new WifiNetworkScoreCache(context);
     84         mNetworkScoreManager = networkScoreManager;
     85         mConnectivityManager = connectivityManager;
     86         mCallback = callback;
     87     }
     88 
     89     public void setListening(boolean listening) {
     90         if (listening) {
     91             mNetworkScoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
     92                     mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
     93             mWifiNetworkScoreCache.registerListener(mCacheListener);
     94             mConnectivityManager.registerNetworkCallback(
     95                     mNetworkRequest, mNetworkCallback, mHandler);
     96         } else {
     97             mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI,
     98                     mWifiNetworkScoreCache);
     99             mWifiNetworkScoreCache.unregisterListener();
    100             mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
    101         }
    102     }
    103 
    104     public void handleBroadcast(Intent intent) {
    105         if (mWifiManager == null) {
    106             return;
    107         }
    108         String action = intent.getAction();
    109         if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
    110             updateWifiState();
    111         } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    112             updateWifiState();
    113             final NetworkInfo networkInfo =
    114                     intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    115             connected = networkInfo != null && networkInfo.isConnected();
    116             mWifiInfo = null;
    117             ssid = null;
    118             if (connected) {
    119                 mWifiInfo = mWifiManager.getConnectionInfo();
    120                 if (mWifiInfo != null) {
    121                     if (mWifiInfo.isPasspointAp() || mWifiInfo.isOsuAp()) {
    122                         ssid = mWifiInfo.getPasspointProviderFriendlyName();
    123                     } else {
    124                         ssid = getValidSsid(mWifiInfo);
    125                     }
    126                     updateRssi(mWifiInfo.getRssi());
    127                     maybeRequestNetworkScore();
    128                 }
    129             }
    130             updateStatusLabel();
    131         } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
    132             // Default to -200 as its below WifiManager.MIN_RSSI.
    133             updateRssi(intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200));
    134             updateStatusLabel();
    135         }
    136     }
    137 
    138     private void updateWifiState() {
    139         state = mWifiManager.getWifiState();
    140         enabled = state == WifiManager.WIFI_STATE_ENABLED;
    141     }
    142 
    143     private void updateRssi(int newRssi) {
    144         rssi = newRssi;
    145         level = WifiManager.calculateSignalLevel(rssi, WifiManager.RSSI_LEVELS);
    146     }
    147 
    148     private void maybeRequestNetworkScore() {
    149         NetworkKey networkKey = NetworkKey.createFromWifiInfo(mWifiInfo);
    150         if (mWifiNetworkScoreCache.getScoredNetwork(networkKey) == null) {
    151             mNetworkScoreManager.requestScores(new NetworkKey[]{ networkKey });
    152         }
    153     }
    154 
    155     private void updateStatusLabel() {
    156         final NetworkCapabilities networkCapabilities
    157                 = mConnectivityManager.getNetworkCapabilities(mWifiManager.getCurrentNetwork());
    158         if (networkCapabilities != null) {
    159             if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) {
    160                 statusLabel = mContext.getString(R.string.wifi_status_sign_in_required);
    161                 return;
    162             } else if (networkCapabilities.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
    163                 statusLabel = mContext.getString(R.string.wifi_limited_connection);
    164                 return;
    165             } else if (!networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
    166                 statusLabel = mContext.getString(R.string.wifi_status_no_internet);
    167                 return;
    168             }
    169         }
    170 
    171         ScoredNetwork scoredNetwork =
    172                 mWifiNetworkScoreCache.getScoredNetwork(NetworkKey.createFromWifiInfo(mWifiInfo));
    173         statusLabel = scoredNetwork == null
    174                 ? null : AccessPoint.getSpeedLabel(mContext, scoredNetwork, rssi);
    175     }
    176 
    177     /** Refresh the status label on Locale changed. */
    178     public void refreshLocale() {
    179         updateStatusLabel();
    180         mCallback.run();
    181     }
    182 
    183     private String getValidSsid(WifiInfo info) {
    184         String ssid = info.getSSID();
    185         if (ssid != null && !WifiSsid.NONE.equals(ssid)) {
    186             return ssid;
    187         }
    188         // OK, it's not in the connectionInfo; we have to go hunting for it
    189         List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
    190         int length = networks.size();
    191         for (int i = 0; i < length; i++) {
    192             if (networks.get(i).networkId == info.getNetworkId()) {
    193                 return networks.get(i).SSID;
    194             }
    195         }
    196         return null;
    197     }
    198 }
    199