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