1 /* 2 * Copyright (C) 2014 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.connectivity; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.net.ConnectivityManager; 24 import android.net.EthernetManager; 25 import android.net.LinkAddress; 26 import android.net.LinkProperties; 27 import android.net.Network; 28 import android.net.NetworkInfo; 29 import android.net.wifi.WifiInfo; 30 import android.net.wifi.WifiManager; 31 import android.os.HandlerThread; 32 import android.os.Process; 33 import android.support.annotation.UiThread; 34 import android.telephony.PhoneStateListener; 35 import android.telephony.SignalStrength; 36 import android.telephony.TelephonyManager; 37 import android.text.TextUtils; 38 39 import com.android.settingslib.wifi.AccessPoint; 40 import com.android.settingslib.wifi.WifiTracker; 41 42 import java.util.List; 43 44 /** 45 * Listens for changes to the current connectivity status. 46 */ 47 public class ConnectivityListener implements WifiTracker.WifiListener { 48 49 private static final String TAG = "ConnectivityListener"; 50 51 private final Context mContext; 52 private final Listener mListener; 53 private boolean mStarted; 54 55 private WifiTracker mWifiTracker; 56 private final HandlerThread mBgThread; 57 58 private final ConnectivityManager mConnectivityManager; 59 private final WifiManager mWifiManager; 60 private final EthernetManager mEthernetManager; 61 private WifiNetworkListener mWifiListener; 62 private final BroadcastReceiver mNetworkReceiver = new BroadcastReceiver() { 63 @Override 64 public void onReceive(Context context, Intent intent) { 65 mListener.onConnectivityChange(); 66 } 67 }; 68 private final EthernetManager.Listener mEthernetListener = new EthernetManager.Listener() { 69 @Override 70 public void onAvailabilityChanged(boolean isAvailable) { 71 mListener.onConnectivityChange(); 72 } 73 }; 74 private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 75 @Override 76 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 77 mCellSignalStrength = signalStrength; 78 mListener.onConnectivityChange(); 79 } 80 }; 81 82 private SignalStrength mCellSignalStrength; 83 private int mNetworkType; 84 private String mWifiSsid; 85 private int mWifiSignalStrength; 86 87 public ConnectivityListener(Context context, Listener listener) { 88 mContext = context; 89 mConnectivityManager = (ConnectivityManager) mContext.getSystemService( 90 Context.CONNECTIVITY_SERVICE); 91 mWifiManager = mContext.getSystemService(WifiManager.class); 92 mEthernetManager = mContext.getSystemService(EthernetManager.class); 93 mListener = listener; 94 mBgThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); 95 mBgThread.start(); 96 mWifiTracker = new WifiTracker(context, this, mBgThread.getLooper(), true, true); 97 } 98 99 /** 100 * Starts {@link ConnectivityListener}. 101 * This should be called only from main thread. 102 */ 103 @UiThread 104 public void start() { 105 if (!mStarted) { 106 mStarted = true; 107 updateConnectivityStatus(); 108 mWifiTracker.startTracking(); 109 IntentFilter networkIntentFilter = new IntentFilter(); 110 networkIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 111 networkIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); 112 networkIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 113 114 mContext.registerReceiver(mNetworkReceiver, networkIntentFilter); 115 mEthernetManager.addListener(mEthernetListener); 116 final TelephonyManager telephonyManager = mContext 117 .getSystemService(TelephonyManager.class); 118 if (telephonyManager != null) { 119 telephonyManager.listen(mPhoneStateListener, 120 PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); 121 } 122 } 123 } 124 125 /** 126 * Stops {@link ConnectivityListener}. 127 * This should be called only from main thread. 128 */ 129 @UiThread 130 public void stop() { 131 if (mStarted) { 132 mStarted = false; 133 mWifiTracker.stopTracking(); 134 mContext.unregisterReceiver(mNetworkReceiver); 135 mWifiListener = null; 136 mEthernetManager.removeListener(mEthernetListener); 137 final TelephonyManager telephonyManager = mContext 138 .getSystemService(TelephonyManager.class); 139 if (telephonyManager != null) { 140 telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); 141 } 142 } 143 } 144 145 /** 146 * Causes the background thread to quit. 147 */ 148 public void destroy() { 149 mBgThread.quit(); 150 } 151 152 public void setWifiListener(WifiNetworkListener wifiListener) { 153 mWifiListener = wifiListener; 154 } 155 156 public String getWifiIpAddress() { 157 if (isWifiConnected()) { 158 WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); 159 int ip = wifiInfo.getIpAddress(); 160 return String.format("%d.%d.%d.%d", (ip & 0xff), (ip >> 8 & 0xff), 161 (ip >> 16 & 0xff), (ip >> 24 & 0xff)); 162 } else { 163 return ""; 164 } 165 } 166 167 /** 168 * Return the MAC address of the currently connected Wifi AP. 169 */ 170 public String getWifiMacAddress() { 171 if (isWifiConnected()) { 172 WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); 173 return wifiInfo.getMacAddress(); 174 } else { 175 return ""; 176 } 177 } 178 179 public boolean isEthernetConnected() { 180 return mNetworkType == ConnectivityManager.TYPE_ETHERNET; 181 } 182 183 public boolean isWifiConnected() { 184 return mNetworkType == ConnectivityManager.TYPE_WIFI; 185 } 186 187 public boolean isCellConnected() { 188 return mNetworkType == ConnectivityManager.TYPE_MOBILE; 189 } 190 191 /** 192 * Return whether Ethernet port is available. 193 */ 194 public boolean isEthernetAvailable() { 195 return mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_ETHERNET) 196 && mEthernetManager.isAvailable(); 197 } 198 199 private Network getFirstEthernet() { 200 final Network[] networks = mConnectivityManager.getAllNetworks(); 201 for (final Network network : networks) { 202 NetworkInfo networkInfo = mConnectivityManager.getNetworkInfo(network); 203 if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) { 204 return network; 205 } 206 } 207 return null; 208 } 209 210 public String getEthernetIpAddress() { 211 final Network network = getFirstEthernet(); 212 if (network == null) { 213 return null; 214 } 215 final StringBuilder sb = new StringBuilder(); 216 boolean gotAddress = false; 217 final LinkProperties linkProperties = mConnectivityManager.getLinkProperties(network); 218 for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) { 219 if (gotAddress) { 220 sb.append("\n"); 221 } 222 sb.append(linkAddress.getAddress().getHostAddress()); 223 gotAddress = true; 224 } 225 if (gotAddress) { 226 return sb.toString(); 227 } else { 228 return null; 229 } 230 } 231 232 public int getWifiSignalStrength(int maxLevel) { 233 WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); 234 return WifiManager.calculateSignalLevel(wifiInfo.getRssi(), maxLevel); 235 } 236 237 public int getCellSignalStrength() { 238 if (isCellConnected() && mCellSignalStrength != null) { 239 return mCellSignalStrength.getLevel(); 240 } else { 241 return 0; 242 } 243 } 244 245 /** 246 * Return a list of wifi networks. Ensure that if a wifi network is connected that it appears 247 * as the first item on the list. 248 */ 249 public List<AccessPoint> getAvailableNetworks() { 250 return mWifiTracker.getAccessPoints(); 251 } 252 253 public boolean isWifiEnabledOrEnabling() { 254 return mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED 255 || mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING; 256 } 257 258 public void setWifiEnabled(boolean enable) { 259 mWifiManager.setWifiEnabled(enable); 260 } 261 262 private boolean setNetworkType(int networkType) { 263 boolean hasChanged = mNetworkType != networkType; 264 mNetworkType = networkType; 265 return hasChanged; 266 } 267 268 private boolean updateConnectivityStatus() { 269 NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo(); 270 if (networkInfo == null) { 271 return setNetworkType(ConnectivityManager.TYPE_NONE); 272 } else { 273 switch (networkInfo.getType()) { 274 case ConnectivityManager.TYPE_WIFI: { 275 boolean hasChanged; 276 277 // Determine if this is an open or secure wifi connection. 278 WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); 279 hasChanged = setNetworkType(ConnectivityManager.TYPE_WIFI); 280 281 // Find the SSID of network. 282 String ssid = null; 283 if (wifiInfo != null) { 284 ssid = wifiInfo.getSSID(); 285 if (ssid != null) { 286 ssid = WifiInfo.removeDoubleQuotes(ssid); 287 } 288 } 289 if (!TextUtils.equals(mWifiSsid, ssid)) { 290 hasChanged = true; 291 mWifiSsid = ssid; 292 } 293 294 // Calculate the signal strength. 295 int signalStrength; 296 if (wifiInfo != null) { 297 // Calculate the signal strength between 0 and 3. 298 signalStrength = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), 4); 299 } else { 300 signalStrength = 0; 301 } 302 if (mWifiSignalStrength != signalStrength) { 303 hasChanged = true; 304 mWifiSignalStrength = signalStrength; 305 } 306 return hasChanged; 307 } 308 309 case ConnectivityManager.TYPE_ETHERNET: 310 return setNetworkType(ConnectivityManager.TYPE_ETHERNET); 311 312 case ConnectivityManager.TYPE_MOBILE: 313 return setNetworkType(ConnectivityManager.TYPE_MOBILE); 314 315 default: 316 return setNetworkType(ConnectivityManager.TYPE_NONE); 317 } 318 } 319 } 320 321 @Override 322 public void onWifiStateChanged(int state) { 323 mListener.onConnectivityChange(); 324 } 325 326 @Override 327 public void onConnectedChanged() { 328 329 } 330 331 @Override 332 public void onAccessPointsChanged() { 333 if (mWifiListener != null) { 334 mWifiListener.onWifiListChanged(); 335 } 336 } 337 338 public interface Listener { 339 void onConnectivityChange(); 340 } 341 342 public interface WifiNetworkListener { 343 void onWifiListChanged(); 344 } 345 } 346