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 //////////////////////////////////////////////////////////////////////////////// 6 // Threading considerations: 7 // 8 // This class is designed to meet various threading guarantees starting from the 9 // ones imposed by NetworkChangeNotifier: 10 // - The notifier can be constructed on any thread. 11 // - GetCurrentConnectionType() can be called on any thread. 12 // 13 // The fact that this implementation of NetworkChangeNotifier is backed by a 14 // Java side singleton class (see NetworkChangeNotifier.java) adds another 15 // threading constraint: 16 // - The calls to the Java side (stateful) object must be performed from a 17 // single thread. This object happens to be a singleton which is used on the 18 // application side on the main thread. Therefore all the method calls from 19 // the native NetworkChangeNotifierAndroid class to its Java counterpart are 20 // performed on the main thread. 21 // 22 // This leads to a design involving the following native classes: 23 // 1) NetworkChangeNotifierFactoryAndroid ('factory') 24 // 2) NetworkChangeNotifierDelegateAndroid ('delegate') 25 // 3) NetworkChangeNotifierAndroid ('notifier') 26 // 27 // The factory constructs and owns the delegate. The factory is constructed and 28 // destroyed on the main thread which makes it construct and destroy the 29 // delegate on the main thread too. This guarantees that the calls to the Java 30 // side are performed on the main thread. 31 // Note that after the factory's construction, the factory's creation method can 32 // be called from any thread since the delegate's construction (performing the 33 // JNI calls) already happened on the main thread (when the factory was 34 // constructed). 35 // 36 //////////////////////////////////////////////////////////////////////////////// 37 // Propagation of network change notifications: 38 // 39 // When the factory is requested to create a new instance of the notifier, the 40 // factory passes the delegate to the notifier (without transferring ownership). 41 // Note that there is a one-to-one mapping between the factory and the 42 // delegate as explained above. But the factory naturally creates multiple 43 // instances of the notifier. That means that there is a one-to-many mapping 44 // between delegate and notifier (i.e. a single delegate can be shared by 45 // multiple notifiers). 46 // At construction the notifier (which is also an observer) subscribes to 47 // notifications fired by the delegate. These notifications, received by the 48 // delegate (and forwarded to the notifier(s)), are sent by the Java side 49 // notifier (see NetworkChangeNotifier.java) and are initiated by the Android 50 // platform. 51 // Notifications from the Java side always arrive on the main thread. The 52 // delegate then forwards these notifications to the threads of each observer 53 // (network change notifier). The network change notifier than processes the 54 // state change, and notifies each of its observers on their threads. 55 // 56 // This can also be seen as: 57 // Android platform -> NetworkChangeNotifier (Java) -> 58 // NetworkChangeNotifierDelegateAndroid -> NetworkChangeNotifierAndroid. 59 60 #include "net/android/network_change_notifier_android.h" 61 62 namespace net { 63 64 NetworkChangeNotifierAndroid::~NetworkChangeNotifierAndroid() { 65 delegate_->RemoveObserver(this); 66 } 67 68 NetworkChangeNotifier::ConnectionType 69 NetworkChangeNotifierAndroid::GetCurrentConnectionType() const { 70 return delegate_->GetCurrentConnectionType(); 71 } 72 73 void NetworkChangeNotifierAndroid::OnConnectionTypeChanged() { 74 NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); 75 NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); 76 } 77 78 // static 79 bool NetworkChangeNotifierAndroid::Register(JNIEnv* env) { 80 return NetworkChangeNotifierDelegateAndroid::Register(env); 81 } 82 83 NetworkChangeNotifierAndroid::NetworkChangeNotifierAndroid( 84 NetworkChangeNotifierDelegateAndroid* delegate) 85 : NetworkChangeNotifier(NetworkChangeCalculatorParamsAndroid()), 86 delegate_(delegate) { 87 delegate_->AddObserver(this); 88 } 89 90 // static 91 NetworkChangeNotifier::NetworkChangeCalculatorParams 92 NetworkChangeNotifierAndroid::NetworkChangeCalculatorParamsAndroid() { 93 NetworkChangeCalculatorParams params; 94 // IPAddressChanged is produced immediately prior to ConnectionTypeChanged 95 // so delay IPAddressChanged so they get merged with the following 96 // ConnectionTypeChanged signal. 97 params.ip_address_offline_delay_ = base::TimeDelta::FromSeconds(1); 98 params.ip_address_online_delay_ = base::TimeDelta::FromSeconds(1); 99 params.connection_type_offline_delay_ = base::TimeDelta::FromSeconds(0); 100 params.connection_type_online_delay_ = base::TimeDelta::FromSeconds(0); 101 return params; 102 } 103 104 } // namespace net 105