Home | History | Annotate | Download | only in net
      1 // Copyright 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 package org.chromium.net;
      6 
      7 import android.content.BroadcastReceiver;
      8 import android.content.Context;
      9 import android.content.Intent;
     10 import android.content.IntentFilter;
     11 import android.net.ConnectivityManager;
     12 import android.net.wifi.WifiInfo;
     13 import android.net.wifi.WifiManager;
     14 import android.telephony.TelephonyManager;
     15 import android.util.Log;
     16 
     17 import org.chromium.base.ApplicationState;
     18 import org.chromium.base.ApplicationStatus;
     19 
     20 /**
     21  * Used by the NetworkChangeNotifier to listens to platform changes in connectivity.
     22  * Note that use of this class requires that the app have the platform
     23  * ACCESS_NETWORK_STATE permission.
     24  */
     25 public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver
     26         implements ApplicationStatus.ApplicationStateListener {
     27 
     28     /** Queries the ConnectivityManager for information about the current connection. */
     29     static class ConnectivityManagerDelegate {
     30         private final ConnectivityManager mConnectivityManager;
     31 
     32         ConnectivityManagerDelegate(Context context) {
     33             mConnectivityManager =
     34                     (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
     35         }
     36 
     37         // For testing.
     38         ConnectivityManagerDelegate() {
     39             // All the methods below should be overridden.
     40             mConnectivityManager = null;
     41         }
     42 
     43         boolean activeNetworkExists() {
     44             return mConnectivityManager.getActiveNetworkInfo() != null;
     45         }
     46 
     47         boolean isConnected() {
     48             return mConnectivityManager.getActiveNetworkInfo().isConnected();
     49         }
     50 
     51         int getNetworkType() {
     52             return mConnectivityManager.getActiveNetworkInfo().getType();
     53         }
     54 
     55         int getNetworkSubtype() {
     56             return mConnectivityManager.getActiveNetworkInfo().getSubtype();
     57         }
     58     }
     59 
     60     /** Queries the WifiManager for SSID of the current Wifi connection. */
     61     static class WifiManagerDelegate {
     62         private final WifiManager mWifiManager;
     63 
     64         WifiManagerDelegate(Context context) {
     65             mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
     66         }
     67 
     68         // For testing.
     69         WifiManagerDelegate() {
     70             // All the methods below should be overridden.
     71             mWifiManager = null;
     72         }
     73 
     74         String getWifiSSID() {
     75             WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
     76             if (wifiInfo == null)
     77                 return "";
     78             String ssid = wifiInfo.getSSID();
     79             return ssid == null ? "" : ssid;
     80         }
     81     }
     82 
     83     private static final String TAG = "NetworkChangeNotifierAutoDetect";
     84 
     85     private final NetworkConnectivityIntentFilter mIntentFilter =
     86             new NetworkConnectivityIntentFilter();
     87 
     88     private final Observer mObserver;
     89 
     90     private final Context mContext;
     91     private ConnectivityManagerDelegate mConnectivityManagerDelegate;
     92     private WifiManagerDelegate mWifiManagerDelegate;
     93     private boolean mRegistered;
     94     private int mConnectionType;
     95     private String mWifiSSID;
     96 
     97     /**
     98      * Observer notified on the UI thread whenever a new connection type was detected.
     99      */
    100     public static interface Observer {
    101         public void onConnectionTypeChanged(int newConnectionType);
    102     }
    103 
    104     public NetworkChangeNotifierAutoDetect(Observer observer, Context context) {
    105         mObserver = observer;
    106         mContext = context.getApplicationContext();
    107         mConnectivityManagerDelegate = new ConnectivityManagerDelegate(context);
    108         mWifiManagerDelegate = new WifiManagerDelegate(context);
    109         mConnectionType = getCurrentConnectionType();
    110         mWifiSSID = getCurrentWifiSSID();
    111         ApplicationStatus.registerApplicationStateListener(this);
    112     }
    113 
    114     /**
    115      * Allows overriding the ConnectivityManagerDelegate for tests.
    116      */
    117     void setConnectivityManagerDelegateForTests(ConnectivityManagerDelegate delegate) {
    118         mConnectivityManagerDelegate = delegate;
    119     }
    120 
    121     /**
    122      * Allows overriding the WifiManagerDelegate for tests.
    123      */
    124     void setWifiManagerDelegateForTests(WifiManagerDelegate delegate) {
    125         mWifiManagerDelegate = delegate;
    126     }
    127 
    128     public void destroy() {
    129         unregisterReceiver();
    130     }
    131 
    132     /**
    133      * Register a BroadcastReceiver in the given context.
    134      */
    135     private void registerReceiver() {
    136         if (!mRegistered) {
    137             mRegistered = true;
    138             mContext.registerReceiver(this, mIntentFilter);
    139         }
    140     }
    141 
    142     /**
    143      * Unregister the BroadcastReceiver in the given context.
    144      */
    145     private void unregisterReceiver() {
    146         if (mRegistered) {
    147             mRegistered = false;
    148             mContext.unregisterReceiver(this);
    149         }
    150     }
    151 
    152     public int getCurrentConnectionType() {
    153         // Track exactly what type of connection we have.
    154         if (!mConnectivityManagerDelegate.activeNetworkExists() ||
    155                 !mConnectivityManagerDelegate.isConnected()) {
    156             return NetworkChangeNotifier.CONNECTION_NONE;
    157         }
    158 
    159         switch (mConnectivityManagerDelegate.getNetworkType()) {
    160             case ConnectivityManager.TYPE_ETHERNET:
    161                 return NetworkChangeNotifier.CONNECTION_ETHERNET;
    162             case ConnectivityManager.TYPE_WIFI:
    163                 return NetworkChangeNotifier.CONNECTION_WIFI;
    164             case ConnectivityManager.TYPE_WIMAX:
    165                 return NetworkChangeNotifier.CONNECTION_4G;
    166             case ConnectivityManager.TYPE_BLUETOOTH:
    167                 return NetworkChangeNotifier.CONNECTION_BLUETOOTH;
    168             case ConnectivityManager.TYPE_MOBILE:
    169                 // Use information from TelephonyManager to classify the connection.
    170                 switch (mConnectivityManagerDelegate.getNetworkSubtype()) {
    171                     case TelephonyManager.NETWORK_TYPE_GPRS:
    172                     case TelephonyManager.NETWORK_TYPE_EDGE:
    173                     case TelephonyManager.NETWORK_TYPE_CDMA:
    174                     case TelephonyManager.NETWORK_TYPE_1xRTT:
    175                     case TelephonyManager.NETWORK_TYPE_IDEN:
    176                         return NetworkChangeNotifier.CONNECTION_2G;
    177                     case TelephonyManager.NETWORK_TYPE_UMTS:
    178                     case TelephonyManager.NETWORK_TYPE_EVDO_0:
    179                     case TelephonyManager.NETWORK_TYPE_EVDO_A:
    180                     case TelephonyManager.NETWORK_TYPE_HSDPA:
    181                     case TelephonyManager.NETWORK_TYPE_HSUPA:
    182                     case TelephonyManager.NETWORK_TYPE_HSPA:
    183                     case TelephonyManager.NETWORK_TYPE_EVDO_B:
    184                     case TelephonyManager.NETWORK_TYPE_EHRPD:
    185                     case TelephonyManager.NETWORK_TYPE_HSPAP:
    186                         return NetworkChangeNotifier.CONNECTION_3G;
    187                     case TelephonyManager.NETWORK_TYPE_LTE:
    188                         return NetworkChangeNotifier.CONNECTION_4G;
    189                     default:
    190                         return NetworkChangeNotifier.CONNECTION_UNKNOWN;
    191                 }
    192             default:
    193                 return NetworkChangeNotifier.CONNECTION_UNKNOWN;
    194         }
    195     }
    196 
    197     private String getCurrentWifiSSID() {
    198         if (getCurrentConnectionType() != NetworkChangeNotifier.CONNECTION_WIFI)
    199             return "";
    200         return mWifiManagerDelegate.getWifiSSID();
    201     }
    202 
    203     // BroadcastReceiver
    204     @Override
    205     public void onReceive(Context context, Intent intent) {
    206         connectionTypeChanged();
    207     }
    208 
    209     // ApplicationStatus.ApplicationStateListener
    210     @Override
    211     public void onApplicationStateChange(int newState) {
    212         if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) {
    213             connectionTypeChanged();
    214             registerReceiver();
    215         } else if (newState == ApplicationState.HAS_PAUSED_ACTIVITIES) {
    216             unregisterReceiver();
    217         }
    218     }
    219 
    220     private void connectionTypeChanged() {
    221         int newConnectionType = getCurrentConnectionType();
    222         String newWifiSSID = getCurrentWifiSSID();
    223         if (newConnectionType == mConnectionType && newWifiSSID.equals(mWifiSSID))
    224             return;
    225 
    226         mConnectionType = newConnectionType;
    227         mWifiSSID = newWifiSSID;
    228         Log.d(TAG, "Network connectivity changed, type is: " + mConnectionType);
    229         mObserver.onConnectionTypeChanged(newConnectionType);
    230     }
    231 
    232     private static class NetworkConnectivityIntentFilter extends IntentFilter {
    233         NetworkConnectivityIntentFilter() {
    234             addAction(ConnectivityManager.CONNECTIVITY_ACTION);
    235         }
    236     }
    237 }
    238