- add sources.
[platform/framework/web/crosswalk.git] / src / net / android / java / src / org / chromium / net / NetworkChangeNotifierAutoDetect.java
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
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.NetworkInfo;
13 import android.telephony.TelephonyManager;
14 import android.util.Log;
15
16 import 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  */
23 public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver
24         implements ActivityStatus.StateListener {
25
26     /** Queries the ConnectivityManager for information about the current connection. */
27     static class ConnectivityManagerDelegate {
28         private final ConnectivityManager mConnectivityManager;
29
30         ConnectivityManagerDelegate(Context context) {
31             mConnectivityManager =
32                     (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
33         }
34
35         // For testing.
36         ConnectivityManagerDelegate() {
37             // All the methods below should be overridden.
38             mConnectivityManager = null;
39         }
40
41         boolean activeNetworkExists() {
42             return mConnectivityManager.getActiveNetworkInfo() != null;
43         }
44
45         boolean isConnected() {
46             return mConnectivityManager.getActiveNetworkInfo().isConnected();
47         }
48
49         int getNetworkType() {
50             return mConnectivityManager.getActiveNetworkInfo().getType();
51         }
52
53         int getNetworkSubtype() {
54             return mConnectivityManager.getActiveNetworkInfo().getSubtype();
55         }
56     }
57
58     private static final String TAG = "NetworkChangeNotifierAutoDetect";
59
60     private final NetworkConnectivityIntentFilter mIntentFilter =
61             new NetworkConnectivityIntentFilter();
62
63     private final Observer mObserver;
64
65     private final Context mContext;
66     private ConnectivityManagerDelegate mConnectivityManagerDelegate;
67     private boolean mRegistered;
68     private int mConnectionType;
69
70     /**
71      * Observer notified on the UI thread whenever a new connection type was detected.
72      */
73     public static interface Observer {
74         public void onConnectionTypeChanged(int newConnectionType);
75     }
76
77     public NetworkChangeNotifierAutoDetect(Observer observer, Context context) {
78         mObserver = observer;
79         mContext = context.getApplicationContext();
80         mConnectivityManagerDelegate = new ConnectivityManagerDelegate(context);
81         mConnectionType = getCurrentConnectionType();
82         ActivityStatus.registerStateListener(this);
83     }
84
85     /**
86      * Allows overriding the ConnectivityManagerDelegate for tests.
87      */
88     void setConnectivityManagerDelegateForTests(ConnectivityManagerDelegate delegate) {
89         mConnectivityManagerDelegate = delegate;
90     }
91
92     public void destroy() {
93         unregisterReceiver();
94     }
95
96     /**
97      * Register a BroadcastReceiver in the given context.
98      */
99     private void registerReceiver() {
100         if (!mRegistered) {
101           mRegistered = true;
102           mContext.registerReceiver(this, mIntentFilter);
103         }
104     }
105
106     /**
107      * Unregister the BroadcastReceiver in the given context.
108      */
109     private void unregisterReceiver() {
110         if (mRegistered) {
111            mRegistered = false;
112            mContext.unregisterReceiver(this);
113         }
114     }
115
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;
121         }
122
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;
151                     default:
152                         return NetworkChangeNotifier.CONNECTION_UNKNOWN;
153                 }
154             default:
155                 return NetworkChangeNotifier.CONNECTION_UNKNOWN;
156         }
157     }
158
159     // BroadcastReceiver
160     @Override
161     public void onReceive(Context context, Intent intent) {
162         connectionTypeChanged();
163     }
164
165     // ActivityStatus.StateListener
166     @Override
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();
176             registerReceiver();
177         } else if (state == ActivityStatus.PAUSED) {
178             unregisterReceiver();
179         }
180     }
181
182     private void connectionTypeChanged() {
183         int newConnectionType = getCurrentConnectionType();
184         if (newConnectionType == mConnectionType) return;
185
186         mConnectionType = newConnectionType;
187         Log.d(TAG, "Network connectivity changed, type is: " + mConnectionType);
188         mObserver.onConnectionTypeChanged(newConnectionType);
189     }
190
191     private static class NetworkConnectivityIntentFilter extends IntentFilter {
192         NetworkConnectivityIntentFilter() {
193                 addAction(ConnectivityManager.CONNECTIVITY_ACTION);
194         }
195     }
196 }