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