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