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