1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_ANDROID_H_ 6 #define NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_ANDROID_H_ 7 8 #include <atomic> 9 #include <map> 10 11 #include "base/android/jni_android.h" 12 #include "base/memory/raw_ptr.h" 13 #include "base/observer_list_threadsafe.h" 14 #include "base/synchronization/lock.h" 15 #include "base/threading/thread_checker.h" 16 #include "net/base/net_export.h" 17 #include "net/base/network_change_notifier.h" 18 #include "net/base/network_handle.h" 19 20 namespace net { 21 22 // Delegate used to thread-safely notify NetworkChangeNotifierAndroid whenever a 23 // network connection change notification is signaled by the Java side (on the 24 // JNI thread). 25 // All the methods exposed below must be called exclusively on the JNI thread 26 // unless otherwise stated (e.g. RegisterObserver()/UnregisterObserver()). 27 class NET_EXPORT_PRIVATE NetworkChangeNotifierDelegateAndroid { 28 public: 29 typedef NetworkChangeNotifier::ConnectionCost ConnectionCost; 30 typedef NetworkChangeNotifier::ConnectionType ConnectionType; 31 typedef NetworkChangeNotifier::ConnectionSubtype ConnectionSubtype; 32 typedef NetworkChangeNotifier::NetworkList NetworkList; 33 34 // Observer interface implemented by NetworkChangeNotifierAndroid which 35 // subscribes to network change notifications fired by the delegate (and 36 // initiated by the Java side). 37 class Observer : public NetworkChangeNotifier::NetworkObserver { 38 public: 39 ~Observer() override = default; 40 41 // Updates the current connection type. 42 virtual void OnConnectionTypeChanged() = 0; 43 44 // Updates the current connection cost. 45 virtual void OnConnectionCostChanged() = 0; 46 47 // Updates the current max bandwidth. 48 virtual void OnMaxBandwidthChanged(double max_bandwidth_mbps, 49 ConnectionType connection_type) = 0; 50 51 // Notifies that the default network has gone into a high power mode. 52 virtual void OnDefaultNetworkActive() = 0; 53 }; 54 55 // Initializes native (C++) side of NetworkChangeNotifierAndroid that 56 // communicates with Java NetworkChangeNotifier class. The Java 57 // NetworkChangeNotifier must have been previously initialized with calls 58 // like this: 59 // // Creates global singleton Java NetworkChangeNotifier class instance. 60 // NetworkChangeNotifier.init(); 61 // // Creates Java NetworkChangeNotifierAutoDetect class instance. 62 // NetworkChangeNotifier.registerToReceiveNotificationsAlways(); 63 NetworkChangeNotifierDelegateAndroid(); 64 NetworkChangeNotifierDelegateAndroid( 65 const NetworkChangeNotifierDelegateAndroid&) = delete; 66 NetworkChangeNotifierDelegateAndroid& operator=( 67 const NetworkChangeNotifierDelegateAndroid&) = delete; 68 ~NetworkChangeNotifierDelegateAndroid(); 69 70 // Called from NetworkChangeNotifier.java on the JNI thread whenever 71 // the connection type changes. This updates the current connection type seen 72 // by this class and forwards the notification to the observers that 73 // subscribed through RegisterObserver(). 74 void NotifyConnectionTypeChanged( 75 JNIEnv* env, 76 const base::android::JavaParamRef<jobject>& obj, 77 jint new_connection_type, 78 jlong default_netid); 79 jint GetConnectionType(JNIEnv* env, jobject obj) const; 80 81 // Called from NetworkChangeNotifier.java on the JNI thread whenever 82 // the connection cost changes. This updates the current connection cost seen 83 // by this class and forwards the notification to the observers that 84 // subscribed through RegisterObserver(). 85 void NotifyConnectionCostChanged( 86 JNIEnv* env, 87 const base::android::JavaParamRef<jobject>& obj, 88 jint new_connection_cost); 89 jint GetConnectionCost(JNIEnv* env, jobject obj); 90 91 // Called from NetworkChangeNotifier.java on the JNI thread whenever 92 // the connection subtype changes. This updates the current 93 // max bandwidth and connection subtype seen by this class and forwards the 94 // max bandwidth change to the observers that subscribed through 95 // RegisterObserver(). 96 void NotifyConnectionSubtypeChanged( 97 JNIEnv* env, 98 const base::android::JavaParamRef<jobject>& obj, 99 jint subtype); 100 101 // Called from NetworkChangeNotifier.java on the JNI thread to push 102 // down notifications of network connectivity events. These functions in 103 // turn: 104 // 1) Update |network_map_| and |default_network_|. 105 // 2) Push notifications to NetworkChangeNotifier which in turn pushes 106 // notifications to its NetworkObservers. Note that these functions 107 // perform valuable transformations on the signals like deduplicating. 108 // For descriptions of what individual calls mean, see 109 // NetworkChangeNotifierAutoDetect.Observer functions of the same names. 110 void NotifyOfNetworkConnect(JNIEnv* env, 111 const base::android::JavaParamRef<jobject>& obj, 112 jlong net_id, 113 jint connection_type); 114 void NotifyOfNetworkSoonToDisconnect( 115 JNIEnv* env, 116 const base::android::JavaParamRef<jobject>& obj, 117 jlong net_id); 118 void NotifyOfNetworkDisconnect( 119 JNIEnv* env, 120 const base::android::JavaParamRef<jobject>& obj, 121 jlong net_id); 122 void NotifyPurgeActiveNetworkList( 123 JNIEnv* env, 124 const base::android::JavaParamRef<jobject>& obj, 125 const base::android::JavaParamRef<jlongArray>& active_networks); 126 127 // Called from NetworkActiveNotifier.java on the JNI thread to push down 128 // notifications of default network going in to high power mode. 129 void NotifyOfDefaultNetworkActive(JNIEnv* env); 130 131 // Registers/unregisters the observer which receives notifications from this 132 // delegate. Notifications may be dispatched to the observer from any thread. 133 // |observer| must not invoke (Register|Unregister)Observer() when receiving a 134 // notification, because it would cause a reentrant lock acquisition. 135 // |observer| must unregister itself before 136 // ~NetworkChangeNotifierDelegateAndroid(). 137 void RegisterObserver(Observer* observer); 138 void UnregisterObserver(Observer* observer); 139 140 // Called by NetworkChangeNotifierAndroid to report when a 141 // DefaultNetworkActiveObserver has been added (or removed) so that the 142 // delegate can act on that (possibly enabling or disabling default network 143 // active notifications). 144 void DefaultNetworkActiveObserverRemoved(); 145 void DefaultNetworkActiveObserverAdded(); 146 147 // These methods are simply implementations of NetworkChangeNotifier APIs of 148 // the same name. They can be called from any thread. 149 ConnectionCost GetCurrentConnectionCost(); 150 ConnectionType GetCurrentConnectionType() const; 151 void GetCurrentMaxBandwidthAndConnectionType( 152 double* max_bandwidth_mbps, 153 ConnectionType* connection_type) const; 154 ConnectionType GetNetworkConnectionType(handles::NetworkHandle network) const; 155 handles::NetworkHandle GetCurrentDefaultNetwork() const; 156 void GetCurrentlyConnectedNetworks(NetworkList* network_list) const; 157 bool IsDefaultNetworkActive(); 158 159 // Can be called from any thread if kStoreConnectionSubtype is enabled, 160 // otherwise should be only called from main thread. 161 NetworkChangeNotifier::ConnectionSubtype GetCurrentConnectionSubtype() const; 162 163 // Returns true if NetworkCallback failed to register, indicating that 164 // network-specific callbacks will not be issued. RegisterNetworkCallbackFailed()165 bool RegisterNetworkCallbackFailed() const { 166 return register_network_callback_failed_; 167 } 168 169 static void EnableNetworkChangeNotifierAutoDetectForTest(); 170 171 private: 172 friend class BaseNetworkChangeNotifierAndroidTest; 173 174 // Map of active connected networks and their connection type. 175 typedef std::map<handles::NetworkHandle, ConnectionType> NetworkMap; 176 177 // Converts a Java long[] into a NetworkMap. Expects long[] to contain 178 // repeated instances of: handles::NetworkHandle, ConnectionType 179 static void JavaLongArrayToNetworkMap( 180 JNIEnv* env, 181 const base::android::JavaRef<jlongArray>& long_array, 182 NetworkMap* network_map); 183 184 // These can be selectively enabled/disabled as they might be expensive to 185 // listen to since they could be fired often. 186 void EnableDefaultNetworkActiveNotifications(); 187 void DisableDefaultNetworkActiveNotifications(); 188 189 // Setters that grab appropriate lock. 190 void SetCurrentConnectionCost(ConnectionCost connection_cost); 191 void SetCurrentConnectionType(ConnectionType connection_type); 192 void SetCurrentConnectionSubtype(ConnectionSubtype connection_subtype); 193 void SetCurrentMaxBandwidth(double max_bandwidth); 194 void SetCurrentDefaultNetwork(handles::NetworkHandle default_network); 195 void SetCurrentNetworksAndTypes(NetworkMap network_map); 196 197 // Methods calling the Java side exposed for testing. 198 void SetOnline(); 199 void SetOffline(); 200 void FakeNetworkConnected(handles::NetworkHandle network, 201 ConnectionType type); 202 void FakeNetworkSoonToBeDisconnected(handles::NetworkHandle network); 203 void FakeNetworkDisconnected(handles::NetworkHandle network); 204 void FakePurgeActiveNetworkList(NetworkList networks); 205 void FakeDefaultNetwork(handles::NetworkHandle network, ConnectionType type); 206 void FakeConnectionCostChanged(ConnectionCost cost); 207 void FakeConnectionSubtypeChanged(ConnectionSubtype subtype); 208 void FakeDefaultNetworkActive(); 209 210 THREAD_CHECKER(thread_checker_); 211 212 base::Lock observer_lock_; 213 raw_ptr<Observer> observer_ GUARDED_BY(observer_lock_) = nullptr; 214 215 const base::android::ScopedJavaGlobalRef<jobject> 216 java_network_change_notifier_; 217 // True if NetworkCallback failed to register, indicating that 218 // network-specific callbacks will not be issued. 219 const bool register_network_callback_failed_; 220 base::android::ScopedJavaGlobalRef<jobject> java_network_active_notifier_; 221 222 mutable base::Lock connection_lock_; // Protects the state below. 223 ConnectionType connection_type_; 224 ConnectionSubtype connection_subtype_; 225 ConnectionCost connection_cost_; 226 double connection_max_bandwidth_; 227 handles::NetworkHandle default_network_; 228 NetworkMap network_map_; 229 230 // Used to enable/disable default network active notifications on the Java 231 // side. 232 std::atomic_int default_network_active_observers_ = 0; 233 }; 234 235 } // namespace net 236 237 #endif // NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_ANDROID_H_ 238