NetworkChangeNotifierAutoDetect.java revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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 5package org.chromium.net; 6 7import android.content.BroadcastReceiver; 8import android.content.Context; 9import android.content.Intent; 10import android.content.IntentFilter; 11import android.net.ConnectivityManager; 12import android.telephony.TelephonyManager; 13import android.util.Log; 14 15import org.chromium.base.ActivityStatus; 16 17/** 18 * Used by the NetworkChangeNotifier to listens to platform changes in connectivity. 19 * Note that use of this class requires that the app have the platform 20 * ACCESS_NETWORK_STATE permission. 21 */ 22public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver 23 implements ActivityStatus.StateListener { 24 25 /** Queries the ConnectivityManager for information about the current connection. */ 26 static class ConnectivityManagerDelegate { 27 private final ConnectivityManager mConnectivityManager; 28 29 ConnectivityManagerDelegate(Context context) { 30 mConnectivityManager = 31 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 32 } 33 34 // For testing. 35 ConnectivityManagerDelegate() { 36 // All the methods below should be overridden. 37 mConnectivityManager = null; 38 } 39 40 boolean activeNetworkExists() { 41 return mConnectivityManager.getActiveNetworkInfo() != null; 42 } 43 44 boolean isConnected() { 45 return mConnectivityManager.getActiveNetworkInfo().isConnected(); 46 } 47 48 int getNetworkType() { 49 return mConnectivityManager.getActiveNetworkInfo().getType(); 50 } 51 52 int getNetworkSubtype() { 53 return mConnectivityManager.getActiveNetworkInfo().getSubtype(); 54 } 55 } 56 57 private static final String TAG = "NetworkChangeNotifierAutoDetect"; 58 59 private final NetworkConnectivityIntentFilter mIntentFilter = 60 new NetworkConnectivityIntentFilter(); 61 62 private final Observer mObserver; 63 64 private final Context mContext; 65 private ConnectivityManagerDelegate mConnectivityManagerDelegate; 66 private boolean mRegistered; 67 private int mConnectionType; 68 69 /** 70 * Observer notified on the UI thread whenever a new connection type was detected. 71 */ 72 public static interface Observer { 73 public void onConnectionTypeChanged(int newConnectionType); 74 } 75 76 public NetworkChangeNotifierAutoDetect(Observer observer, Context context) { 77 mObserver = observer; 78 mContext = context.getApplicationContext(); 79 mConnectivityManagerDelegate = new ConnectivityManagerDelegate(context); 80 mConnectionType = getCurrentConnectionType(); 81 ActivityStatus.registerStateListener(this); 82 } 83 84 /** 85 * Allows overriding the ConnectivityManagerDelegate for tests. 86 */ 87 void setConnectivityManagerDelegateForTests(ConnectivityManagerDelegate delegate) { 88 mConnectivityManagerDelegate = delegate; 89 } 90 91 public void destroy() { 92 unregisterReceiver(); 93 } 94 95 /** 96 * Register a BroadcastReceiver in the given context. 97 */ 98 private void registerReceiver() { 99 if (!mRegistered) { 100 mRegistered = true; 101 mContext.registerReceiver(this, mIntentFilter); 102 } 103 } 104 105 /** 106 * Unregister the BroadcastReceiver in the given context. 107 */ 108 private void unregisterReceiver() { 109 if (mRegistered) { 110 mRegistered = false; 111 mContext.unregisterReceiver(this); 112 } 113 } 114 115 public int getCurrentConnectionType() { 116 // Track exactly what type of connection we have. 117 if (!mConnectivityManagerDelegate.activeNetworkExists() || 118 !mConnectivityManagerDelegate.isConnected()) { 119 return NetworkChangeNotifier.CONNECTION_NONE; 120 } 121 122 switch (mConnectivityManagerDelegate.getNetworkType()) { 123 case ConnectivityManager.TYPE_ETHERNET: 124 return NetworkChangeNotifier.CONNECTION_ETHERNET; 125 case ConnectivityManager.TYPE_WIFI: 126 return NetworkChangeNotifier.CONNECTION_WIFI; 127 case ConnectivityManager.TYPE_WIMAX: 128 return NetworkChangeNotifier.CONNECTION_4G; 129 case ConnectivityManager.TYPE_MOBILE: 130 // Use information from TelephonyManager to classify the connection. 131 switch (mConnectivityManagerDelegate.getNetworkSubtype()) { 132 case TelephonyManager.NETWORK_TYPE_GPRS: 133 case TelephonyManager.NETWORK_TYPE_EDGE: 134 case TelephonyManager.NETWORK_TYPE_CDMA: 135 case TelephonyManager.NETWORK_TYPE_1xRTT: 136 case TelephonyManager.NETWORK_TYPE_IDEN: 137 return NetworkChangeNotifier.CONNECTION_2G; 138 case TelephonyManager.NETWORK_TYPE_UMTS: 139 case TelephonyManager.NETWORK_TYPE_EVDO_0: 140 case TelephonyManager.NETWORK_TYPE_EVDO_A: 141 case TelephonyManager.NETWORK_TYPE_HSDPA: 142 case TelephonyManager.NETWORK_TYPE_HSUPA: 143 case TelephonyManager.NETWORK_TYPE_HSPA: 144 case TelephonyManager.NETWORK_TYPE_EVDO_B: 145 case TelephonyManager.NETWORK_TYPE_EHRPD: 146 case TelephonyManager.NETWORK_TYPE_HSPAP: 147 return NetworkChangeNotifier.CONNECTION_3G; 148 case TelephonyManager.NETWORK_TYPE_LTE: 149 return NetworkChangeNotifier.CONNECTION_4G; 150 default: 151 return NetworkChangeNotifier.CONNECTION_UNKNOWN; 152 } 153 default: 154 return NetworkChangeNotifier.CONNECTION_UNKNOWN; 155 } 156 } 157 158 // BroadcastReceiver 159 @Override 160 public void onReceive(Context context, Intent intent) { 161 connectionTypeChanged(); 162 } 163 164 // ActivityStatus.StateListener 165 @Override 166 public void onActivityStateChange(int state) { 167 if (state == ActivityStatus.RESUMED) { 168 // Note that this also covers the case where the main activity is created. The CREATED 169 // event is always followed by the RESUMED event. This is a temporary "hack" until 170 // http://crbug.com/176837 is fixed. The CREATED event can't be used reliably for now 171 // since its notification is deferred. This means that it can immediately follow a 172 // DESTROYED/STOPPED/... event which is problematic. 173 // TODO(pliard): fix http://crbug.com/176837. 174 connectionTypeChanged(); 175 registerReceiver(); 176 } else if (state == ActivityStatus.PAUSED) { 177 unregisterReceiver(); 178 } 179 } 180 181 private void connectionTypeChanged() { 182 int newConnectionType = getCurrentConnectionType(); 183 if (newConnectionType == mConnectionType) return; 184 185 mConnectionType = newConnectionType; 186 Log.d(TAG, "Network connectivity changed, type is: " + mConnectionType); 187 mObserver.onConnectionTypeChanged(newConnectionType); 188 } 189 190 private static class NetworkConnectivityIntentFilter extends IntentFilter { 191 NetworkConnectivityIntentFilter() { 192 addAction(ConnectivityManager.CONNECTIVITY_ACTION); 193 } 194 } 195} 196