NetworkChangeNotifierAutoDetect.java revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 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.net.NetworkInfo; 13import android.telephony.TelephonyManager; 14import android.util.Log; 15 16import org.chromium.base.ActivityStatus; 17 18/** 19 * Used by the NetworkChangeNotifier to listens to platform changes in connectivity. 20 * Note that use of this class requires that the app have the platform 21 * ACCESS_NETWORK_STATE permission. 22 */ 23public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver 24 implements ActivityStatus.Listener { 25 26 /** Queries the ConnectivityManager for information about the current connection. */ 27 static class ConnectivityManagerDelegate { 28 private ConnectivityManager mConnectivityManager; 29 30 ConnectivityManagerDelegate(Context context) { 31 if (context != null) { 32 mConnectivityManager = (ConnectivityManager) 33 context.getSystemService(Context.CONNECTIVITY_SERVICE); 34 } 35 } 36 37 boolean activeNetworkExists() { 38 return mConnectivityManager != null && 39 mConnectivityManager.getActiveNetworkInfo() != null; 40 } 41 42 int getNetworkType() { 43 return mConnectivityManager.getActiveNetworkInfo().getType(); 44 } 45 46 int getNetworkSubtype() { 47 return mConnectivityManager.getActiveNetworkInfo().getSubtype(); 48 } 49 } 50 51 private static final String TAG = "NetworkChangeNotifierAutoDetect"; 52 53 private final NetworkConnectivityIntentFilter mIntentFilter = 54 new NetworkConnectivityIntentFilter(); 55 56 private final Observer mObserver; 57 58 private final Context mContext; 59 private ConnectivityManagerDelegate mConnectivityManagerDelegate; 60 private boolean mRegistered; 61 private int mConnectionType; 62 63 /** 64 * Observer notified on the UI thread whenever a new connection type was detected. 65 */ 66 public static interface Observer { 67 public void onConnectionTypeChanged(int newConnectionType); 68 } 69 70 public NetworkChangeNotifierAutoDetect(Observer observer, Context context) { 71 mObserver = observer; 72 mContext = context; 73 mConnectivityManagerDelegate = new ConnectivityManagerDelegate(context); 74 mConnectionType = currentConnectionType(context); 75 76 ActivityStatus status = ActivityStatus.getInstance(); 77 if (!status.isPaused()) { 78 registerReceiver(); 79 } 80 status.registerListener(this); 81 } 82 83 /** 84 * Allows overriding the ConnectivityManagerDelegate for tests. 85 */ 86 void setConnectivityManagerDelegateForTests(ConnectivityManagerDelegate delegate) { 87 mConnectivityManagerDelegate = delegate; 88 } 89 90 public void destroy() { 91 unregisterReceiver(); 92 } 93 94 /** 95 * Register a BroadcastReceiver in the given context. 96 */ 97 private void registerReceiver() { 98 if (!mRegistered) { 99 mRegistered = true; 100 mContext.registerReceiver(this, mIntentFilter); 101 } 102 } 103 104 /** 105 * Unregister the BroadcastReceiver in the given context. 106 */ 107 private void unregisterReceiver() { 108 if (mRegistered) { 109 mRegistered = false; 110 mContext.unregisterReceiver(this); 111 } 112 } 113 114 private int currentConnectionType(Context context) { 115 // Track exactly what type of connection we have. 116 if (!mConnectivityManagerDelegate.activeNetworkExists()) { 117 return NetworkChangeNotifier.CONNECTION_NONE; 118 } 119 120 switch (mConnectivityManagerDelegate.getNetworkType()) { 121 case ConnectivityManager.TYPE_ETHERNET: 122 return NetworkChangeNotifier.CONNECTION_ETHERNET; 123 case ConnectivityManager.TYPE_WIFI: 124 return NetworkChangeNotifier.CONNECTION_WIFI; 125 case ConnectivityManager.TYPE_WIMAX: 126 return NetworkChangeNotifier.CONNECTION_4G; 127 case ConnectivityManager.TYPE_MOBILE: 128 // Use information from TelephonyManager to classify the connection. 129 switch (mConnectivityManagerDelegate.getNetworkSubtype()) { 130 case TelephonyManager.NETWORK_TYPE_GPRS: 131 case TelephonyManager.NETWORK_TYPE_EDGE: 132 case TelephonyManager.NETWORK_TYPE_CDMA: 133 case TelephonyManager.NETWORK_TYPE_1xRTT: 134 case TelephonyManager.NETWORK_TYPE_IDEN: 135 return NetworkChangeNotifier.CONNECTION_2G; 136 case TelephonyManager.NETWORK_TYPE_UMTS: 137 case TelephonyManager.NETWORK_TYPE_EVDO_0: 138 case TelephonyManager.NETWORK_TYPE_EVDO_A: 139 case TelephonyManager.NETWORK_TYPE_HSDPA: 140 case TelephonyManager.NETWORK_TYPE_HSUPA: 141 case TelephonyManager.NETWORK_TYPE_HSPA: 142 case TelephonyManager.NETWORK_TYPE_EVDO_B: 143 case TelephonyManager.NETWORK_TYPE_EHRPD: 144 case TelephonyManager.NETWORK_TYPE_HSPAP: 145 return NetworkChangeNotifier.CONNECTION_3G; 146 case TelephonyManager.NETWORK_TYPE_LTE: 147 return NetworkChangeNotifier.CONNECTION_4G; 148 default: 149 return NetworkChangeNotifier.CONNECTION_UNKNOWN; 150 } 151 default: 152 return NetworkChangeNotifier.CONNECTION_UNKNOWN; 153 } 154 } 155 156 // BroadcastReceiver 157 @Override 158 public void onReceive(Context context, Intent intent) { 159 boolean noConnection = 160 intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); 161 int newConnectionType = noConnection ? 162 NetworkChangeNotifier.CONNECTION_NONE : currentConnectionType(context); 163 164 if (newConnectionType != mConnectionType) { 165 mConnectionType = newConnectionType; 166 Log.d(TAG, "Network connectivity changed, type is: " + mConnectionType); 167 mObserver.onConnectionTypeChanged(newConnectionType); 168 } 169 } 170 171 // AcitivityStatus.Listener 172 @Override 173 public void onActivityStatusChanged(boolean isPaused) { 174 if (isPaused) { 175 unregisterReceiver(); 176 } else { 177 registerReceiver(); 178 } 179 } 180 181 private static class NetworkConnectivityIntentFilter extends IntentFilter { 182 NetworkConnectivityIntentFilter() { 183 addAction(ConnectivityManager.CONNECTIVITY_ACTION); 184 } 185 } 186} 187