Home | History | Annotate | Download | only in connectivity
      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