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.
5 package org.chromium.net;
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.NetworkInfo;
13 import android.telephony.TelephonyManager;
14 import android.util.Log;
16 import org.chromium.base.ActivityStatus;
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.
23 public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver
24 implements ActivityStatus.StateListener {
26 /** Queries the ConnectivityManager for information about the current connection. */
27 static class ConnectivityManagerDelegate {
28 private final ConnectivityManager mConnectivityManager;
30 ConnectivityManagerDelegate(Context context) {
31 mConnectivityManager =
32 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
36 ConnectivityManagerDelegate() {
37 // All the methods below should be overridden.
38 mConnectivityManager = null;
41 boolean activeNetworkExists() {
42 return mConnectivityManager.getActiveNetworkInfo() != null;
45 boolean isConnected() {
46 return mConnectivityManager.getActiveNetworkInfo().isConnected();
49 int getNetworkType() {
50 return mConnectivityManager.getActiveNetworkInfo().getType();
53 int getNetworkSubtype() {
54 return mConnectivityManager.getActiveNetworkInfo().getSubtype();
58 private static final String TAG = "NetworkChangeNotifierAutoDetect";
60 private final NetworkConnectivityIntentFilter mIntentFilter =
61 new NetworkConnectivityIntentFilter();
63 private final Observer mObserver;
65 private final Context mContext;
66 private ConnectivityManagerDelegate mConnectivityManagerDelegate;
67 private boolean mRegistered;
68 private int mConnectionType;
71 * Observer notified on the UI thread whenever a new connection type was detected.
73 public static interface Observer {
74 public void onConnectionTypeChanged(int newConnectionType);
77 public NetworkChangeNotifierAutoDetect(Observer observer, Context context) {
79 mContext = context.getApplicationContext();
80 mConnectivityManagerDelegate = new ConnectivityManagerDelegate(context);
81 mConnectionType = getCurrentConnectionType();
82 ActivityStatus.registerStateListener(this);
86 * Allows overriding the ConnectivityManagerDelegate for tests.
88 void setConnectivityManagerDelegateForTests(ConnectivityManagerDelegate delegate) {
89 mConnectivityManagerDelegate = delegate;
92 public void destroy() {
97 * Register a BroadcastReceiver in the given context.
99 private void registerReceiver() {
102 mContext.registerReceiver(this, mIntentFilter);
107 * Unregister the BroadcastReceiver in the given context.
109 private void unregisterReceiver() {
112 mContext.unregisterReceiver(this);
116 public int getCurrentConnectionType() {
117 // Track exactly what type of connection we have.
118 if (!mConnectivityManagerDelegate.activeNetworkExists() ||
119 !mConnectivityManagerDelegate.isConnected()) {
120 return NetworkChangeNotifier.CONNECTION_NONE;
123 switch (mConnectivityManagerDelegate.getNetworkType()) {
124 case ConnectivityManager.TYPE_ETHERNET:
125 return NetworkChangeNotifier.CONNECTION_ETHERNET;
126 case ConnectivityManager.TYPE_WIFI:
127 return NetworkChangeNotifier.CONNECTION_WIFI;
128 case ConnectivityManager.TYPE_WIMAX:
129 return NetworkChangeNotifier.CONNECTION_4G;
130 case ConnectivityManager.TYPE_MOBILE:
131 // Use information from TelephonyManager to classify the connection.
132 switch (mConnectivityManagerDelegate.getNetworkSubtype()) {
133 case TelephonyManager.NETWORK_TYPE_GPRS:
134 case TelephonyManager.NETWORK_TYPE_EDGE:
135 case TelephonyManager.NETWORK_TYPE_CDMA:
136 case TelephonyManager.NETWORK_TYPE_1xRTT:
137 case TelephonyManager.NETWORK_TYPE_IDEN:
138 return NetworkChangeNotifier.CONNECTION_2G;
139 case TelephonyManager.NETWORK_TYPE_UMTS:
140 case TelephonyManager.NETWORK_TYPE_EVDO_0:
141 case TelephonyManager.NETWORK_TYPE_EVDO_A:
142 case TelephonyManager.NETWORK_TYPE_HSDPA:
143 case TelephonyManager.NETWORK_TYPE_HSUPA:
144 case TelephonyManager.NETWORK_TYPE_HSPA:
145 case TelephonyManager.NETWORK_TYPE_EVDO_B:
146 case TelephonyManager.NETWORK_TYPE_EHRPD:
147 case TelephonyManager.NETWORK_TYPE_HSPAP:
148 return NetworkChangeNotifier.CONNECTION_3G;
149 case TelephonyManager.NETWORK_TYPE_LTE:
150 return NetworkChangeNotifier.CONNECTION_4G;
152 return NetworkChangeNotifier.CONNECTION_UNKNOWN;
155 return NetworkChangeNotifier.CONNECTION_UNKNOWN;
161 public void onReceive(Context context, Intent intent) {
162 connectionTypeChanged();
165 // ActivityStatus.StateListener
167 public void onActivityStateChange(int state) {
168 if (state == ActivityStatus.RESUMED) {
169 // Note that this also covers the case where the main activity is created. The CREATED
170 // event is always followed by the RESUMED event. This is a temporary "hack" until
171 // http://crbug.com/176837 is fixed. The CREATED event can't be used reliably for now
172 // since its notification is deferred. This means that it can immediately follow a
173 // DESTROYED/STOPPED/... event which is problematic.
174 // TODO(pliard): fix http://crbug.com/176837.
175 connectionTypeChanged();
177 } else if (state == ActivityStatus.PAUSED) {
178 unregisterReceiver();
182 private void connectionTypeChanged() {
183 int newConnectionType = getCurrentConnectionType();
184 if (newConnectionType == mConnectionType) return;
186 mConnectionType = newConnectionType;
187 Log.d(TAG, "Network connectivity changed, type is: " + mConnectionType);
188 mObserver.onConnectionTypeChanged(newConnectionType);
191 private static class NetworkConnectivityIntentFilter extends IntentFilter {
192 NetworkConnectivityIntentFilter() {
193 addAction(ConnectivityManager.CONNECTIVITY_ACTION);