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