- add sources.
[platform/framework/web/crosswalk.git] / src / net / android / java / src / org / chromium / net / NetworkChangeNotifier.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.Context;
8
9 import org.chromium.base.CalledByNative;
10 import org.chromium.base.JNINamespace;
11 import org.chromium.base.NativeClassQualifiedName;
12 import org.chromium.base.ObserverList;
13
14 import java.util.ArrayList;
15
16 /**
17  * Triggers updates to the underlying network state in Chrome.
18  *
19  * By default, connectivity is assumed and changes must pushed from the embedder via the
20  * forceConnectivityState function.
21  * Embedders may choose to have this class auto-detect changes in network connectivity by invoking
22  * the setAutoDetectConnectivityState function.
23  *
24  * WARNING: This class is not thread-safe.
25  */
26 @JNINamespace("net")
27 public class NetworkChangeNotifier {
28     /**
29      * Alerted when the connection type of the network changes.
30      * The alert is fired on the UI thread.
31      */
32     public interface ConnectionTypeObserver {
33         public void onConnectionTypeChanged(int connectionType);
34     }
35
36     // These constants must always match the ones in network_change_notifier.h.
37     public static final int CONNECTION_UNKNOWN = 0;
38     public static final int CONNECTION_ETHERNET = 1;
39     public static final int CONNECTION_WIFI = 2;
40     public static final int CONNECTION_2G = 3;
41     public static final int CONNECTION_3G = 4;
42     public static final int CONNECTION_4G = 5;
43     public static final int CONNECTION_NONE = 6;
44
45     private final Context mContext;
46     private final ArrayList<Integer> mNativeChangeNotifiers;
47     private final ObserverList<ConnectionTypeObserver> mConnectionTypeObservers;
48     private NetworkChangeNotifierAutoDetect mAutoDetector;
49     private int mCurrentConnectionType = CONNECTION_UNKNOWN;
50
51     private static NetworkChangeNotifier sInstance;
52
53     private NetworkChangeNotifier(Context context) {
54         mContext = context.getApplicationContext();
55         mNativeChangeNotifiers = new ArrayList<Integer>();
56         mConnectionTypeObservers = new ObserverList<ConnectionTypeObserver>();
57     }
58
59     /**
60      * Initializes the singleton once.
61      */
62     @CalledByNative
63     public static NetworkChangeNotifier init(Context context) {
64         if (sInstance == null) {
65             sInstance = new NetworkChangeNotifier(context);
66         }
67         return sInstance;
68     }
69
70     public static boolean isInitialized() {
71         return sInstance != null;
72     }
73
74     static void resetInstanceForTests(Context context) {
75         sInstance = new NetworkChangeNotifier(context);
76     }
77
78     @CalledByNative
79     public int getCurrentConnectionType() {
80         return mCurrentConnectionType;
81     }
82
83     /**
84      * Adds a native-side observer.
85      */
86     @CalledByNative
87     public void addNativeObserver(int nativeChangeNotifier) {
88         mNativeChangeNotifiers.add(nativeChangeNotifier);
89     }
90
91     /**
92      * Removes a native-side observer.
93      */
94     @CalledByNative
95     public void removeNativeObserver(int nativeChangeNotifier) {
96         // Please keep the cast performing the boxing below. It ensures that the right method
97         // overload is used. ArrayList<T> has both remove(int index) and remove(T element).
98         mNativeChangeNotifiers.remove((Integer) nativeChangeNotifier);
99     }
100
101     /**
102      * Returns the singleton instance.
103      */
104     public static NetworkChangeNotifier getInstance() {
105         assert sInstance != null;
106         return sInstance;
107     }
108
109     /**
110      * Enables auto detection of the current network state based on notifications from the system.
111      * Note that passing true here requires the embedding app have the platform ACCESS_NETWORK_STATE
112      * permission.
113      *
114      * @param shouldAutoDetect true if the NetworkChangeNotifier should listen for system changes in
115      *    network connectivity.
116      */
117     public static void setAutoDetectConnectivityState(boolean shouldAutoDetect) {
118         getInstance().setAutoDetectConnectivityStateInternal(shouldAutoDetect);
119     }
120
121     private void destroyAutoDetector() {
122         if (mAutoDetector != null) {
123             mAutoDetector.destroy();
124             mAutoDetector = null;
125         }
126     }
127
128     private void setAutoDetectConnectivityStateInternal(boolean shouldAutoDetect) {
129         if (shouldAutoDetect) {
130             if (mAutoDetector == null) {
131                 mAutoDetector = new NetworkChangeNotifierAutoDetect(
132                     new NetworkChangeNotifierAutoDetect.Observer() {
133                         @Override
134                         public void onConnectionTypeChanged(int newConnectionType) {
135                             updateCurrentConnectionType(newConnectionType);
136                         }
137                     },
138                     mContext);
139                 mCurrentConnectionType = mAutoDetector.getCurrentConnectionType();
140             }
141         } else {
142             destroyAutoDetector();
143         }
144     }
145
146     /**
147      * Updates the perceived network state when not auto-detecting changes to connectivity.
148      *
149      * @param networkAvailable True if the NetworkChangeNotifier should perceive a "connected"
150      *    state, false implies "disconnected".
151      */
152     @CalledByNative
153     public static void forceConnectivityState(boolean networkAvailable) {
154         setAutoDetectConnectivityState(false);
155         getInstance().forceConnectivityStateInternal(networkAvailable);
156     }
157
158     private void forceConnectivityStateInternal(boolean forceOnline) {
159         boolean connectionCurrentlyExists = mCurrentConnectionType != CONNECTION_NONE;
160         if (connectionCurrentlyExists != forceOnline) {
161             updateCurrentConnectionType(forceOnline ? CONNECTION_UNKNOWN : CONNECTION_NONE);
162         }
163     }
164
165     private void updateCurrentConnectionType(int newConnectionType) {
166         mCurrentConnectionType = newConnectionType;
167         notifyObserversOfConnectionTypeChange(newConnectionType);
168     }
169
170     /**
171      * Alerts all observers of a connection change.
172      */
173     void notifyObserversOfConnectionTypeChange(int newConnectionType) {
174         for (Integer nativeChangeNotifier : mNativeChangeNotifiers) {
175             nativeNotifyConnectionTypeChanged(nativeChangeNotifier, newConnectionType);
176         }
177         for (ConnectionTypeObserver observer : mConnectionTypeObservers) {
178             observer.onConnectionTypeChanged(newConnectionType);
179         }
180     }
181
182     /**
183      * Adds an observer for any connection type changes.
184      */
185     public static void addConnectionTypeObserver(ConnectionTypeObserver observer) {
186         getInstance().addConnectionTypeObserverInternal(observer);
187     }
188
189     private void addConnectionTypeObserverInternal(ConnectionTypeObserver observer) {
190         if (!mConnectionTypeObservers.hasObserver(observer)) {
191             mConnectionTypeObservers.addObserver(observer);
192         }
193     }
194
195     /**
196      * Removes an observer for any connection type changes.
197      */
198     public static void removeConnectionTypeObserver(ConnectionTypeObserver observer) {
199         getInstance().removeConnectionTypeObserverInternal(observer);
200     }
201
202     private void removeConnectionTypeObserverInternal(ConnectionTypeObserver observer) {
203         mConnectionTypeObservers.removeObserver(observer);
204     }
205
206     @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
207     private native void nativeNotifyConnectionTypeChanged(int nativePtr, int newConnectionType);
208
209     @NativeClassQualifiedName("NetworkChangeNotifierDelegateAndroid")
210     private native int nativeGetConnectionType(int nativePtr);
211
212     // For testing only.
213     public static NetworkChangeNotifierAutoDetect getAutoDetectorForTest() {
214         return getInstance().mAutoDetector;
215     }
216
217     /**
218      * Checks if there currently is connectivity.
219      */
220     public static boolean isOnline() {
221         int connectionType = getInstance().getCurrentConnectionType();
222         return connectionType != CONNECTION_UNKNOWN && connectionType != CONNECTION_NONE;
223     }
224 }