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 maximum bandwidth of the connection changes. This updates the current 93 // max bandwidth seen by this class and forwards the notification to the 94 // observers that subscribed through RegisterObserver(). 95 void NotifyMaxBandwidthChanged( 96 JNIEnv* env, 97 const base::android::JavaParamRef<jobject>& obj, 98 jint subtype); 99 100 // Called from NetworkChangeNotifier.java on the JNI thread to push 101 // down notifications of network connectivity events. These functions in 102 // turn: 103 // 1) Update |network_map_| and |default_network_|. 104 // 2) Push notifications to NetworkChangeNotifier which in turn pushes 105 // notifications to its NetworkObservers. Note that these functions 106 // perform valuable transformations on the signals like deduplicating. 107 // For descriptions of what individual calls mean, see 108 // NetworkChangeNotifierAutoDetect.Observer functions of the same names. 109 void NotifyOfNetworkConnect(JNIEnv* env, 110 const base::android::JavaParamRef<jobject>& obj, 111 jlong net_id, 112 jint connection_type); 113 void NotifyOfNetworkSoonToDisconnect( 114 JNIEnv* env, 115 const base::android::JavaParamRef<jobject>& obj, 116 jlong net_id); 117 void NotifyOfNetworkDisconnect( 118 JNIEnv* env, 119 const base::android::JavaParamRef<jobject>& obj, 120 jlong net_id); 121 void NotifyPurgeActiveNetworkList( 122 JNIEnv* env, 123 const base::android::JavaParamRef<jobject>& obj, 124 const base::android::JavaParamRef<jlongArray>& active_networks); 125 126 // Called from NetworkActiveNotifier.java on the JNI thread to push down 127 // notifications of default network going in to high power mode. 128 void NotifyOfDefaultNetworkActive(JNIEnv* env); 129 130 // Registers/unregisters the observer which receives notifications from this 131 // delegate. Notifications may be dispatched to the observer from any thread. 132 // |observer| must not invoke (Register|Unregister)Observer() when receiving a 133 // notification, because it would cause a reentrant lock acquisition. 134 // |observer| must unregister itself before 135 // ~NetworkChangeNotifierDelegateAndroid(). 136 void RegisterObserver(Observer* observer); 137 void UnregisterObserver(Observer* observer); 138 139 // Called by NetworkChangeNotifierAndroid to report when a 140 // DefaultNetworkActiveObserver has been added (or removed) so that the 141 // delegate can act on that (possibly enabling or disabling default network 142 // active notifications). 143 void DefaultNetworkActiveObserverRemoved(); 144 void DefaultNetworkActiveObserverAdded(); 145 146 // These methods are simply implementations of NetworkChangeNotifier APIs of 147 // the same name. They can be called from any thread. 148 ConnectionCost GetCurrentConnectionCost(); 149 ConnectionType GetCurrentConnectionType() const; 150 void GetCurrentMaxBandwidthAndConnectionType( 151 double* max_bandwidth_mbps, 152 ConnectionType* connection_type) const; 153 ConnectionType GetNetworkConnectionType(handles::NetworkHandle network) const; 154 handles::NetworkHandle GetCurrentDefaultNetwork() const; 155 void GetCurrentlyConnectedNetworks(NetworkList* network_list) const; 156 bool IsDefaultNetworkActive(); 157 158 // Can only be called from the main (Java) thread. 159 NetworkChangeNotifier::ConnectionSubtype GetCurrentConnectionSubtype() const; 160 161 // Returns true if NetworkCallback failed to register, indicating that 162 // network-specific callbacks will not be issued. RegisterNetworkCallbackFailed()163 bool RegisterNetworkCallbackFailed() const { 164 return register_network_callback_failed_; 165 } 166 167 static void EnableNetworkChangeNotifierAutoDetectForTest(); 168 169 private: 170 friend class BaseNetworkChangeNotifierAndroidTest; 171 172 // Map of active connected networks and their connection type. 173 typedef std::map<handles::NetworkHandle, ConnectionType> NetworkMap; 174 175 // Converts a Java long[] into a NetworkMap. Expects long[] to contain 176 // repeated instances of: handles::NetworkHandle, ConnectionType 177 static void JavaLongArrayToNetworkMap( 178 JNIEnv* env, 179 const base::android::JavaRef<jlongArray>& long_array, 180 NetworkMap* network_map); 181 182 // These can be selectively enabled/disabled as they might be expensive to 183 // listen to since they could be fired often. 184 void EnableDefaultNetworkActiveNotifications(); 185 void DisableDefaultNetworkActiveNotifications(); 186 187 // Setters that grab appropriate lock. 188 void SetCurrentConnectionCost(ConnectionCost connection_cost); 189 void SetCurrentConnectionType(ConnectionType connection_type); 190 void SetCurrentMaxBandwidth(double max_bandwidth); 191 void SetCurrentDefaultNetwork(handles::NetworkHandle default_network); 192 void SetCurrentNetworksAndTypes(NetworkMap network_map); 193 194 // Methods calling the Java side exposed for testing. 195 void SetOnline(); 196 void SetOffline(); 197 void FakeNetworkConnected(handles::NetworkHandle network, 198 ConnectionType type); 199 void FakeNetworkSoonToBeDisconnected(handles::NetworkHandle network); 200 void FakeNetworkDisconnected(handles::NetworkHandle network); 201 void FakePurgeActiveNetworkList(NetworkList networks); 202 void FakeDefaultNetwork(handles::NetworkHandle network, ConnectionType type); 203 void FakeConnectionCostChanged(ConnectionCost cost); 204 void FakeConnectionSubtypeChanged(ConnectionSubtype subtype); 205 void FakeDefaultNetworkActive(); 206 207 THREAD_CHECKER(thread_checker_); 208 209 base::Lock observer_lock_; 210 raw_ptr<Observer> observer_ GUARDED_BY(observer_lock_) = nullptr; 211 212 const base::android::ScopedJavaGlobalRef<jobject> 213 java_network_change_notifier_; 214 // True if NetworkCallback failed to register, indicating that 215 // network-specific callbacks will not be issued. 216 const bool register_network_callback_failed_; 217 base::android::ScopedJavaGlobalRef<jobject> java_network_active_notifier_; 218 // True if DefaultNetworkActive type of info are not supported, indicating 219 // that we shouldn't try to enable its callback or query its status. 220 const bool is_default_network_active_api_supported_; 221 222 mutable base::Lock connection_lock_; // Protects the state below. 223 ConnectionType connection_type_; 224 ConnectionCost connection_cost_; 225 double connection_max_bandwidth_; 226 handles::NetworkHandle default_network_; 227 NetworkMap network_map_; 228 229 // Used to enable/disable default network active notifications on the Java 230 // side. 231 std::atomic_int default_network_active_observers_ = 0; 232 }; 233 234 } // namespace net 235 236 #endif // NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_ANDROID_H_ 237