diff options
Diffstat (limited to 'net/android/network_change_notifier_delegate_android.cc')
-rw-r--r-- | net/android/network_change_notifier_delegate_android.cc | 199 |
1 files changed, 198 insertions, 1 deletions
diff --git a/net/android/network_change_notifier_delegate_android.cc b/net/android/network_change_notifier_delegate_android.cc index be4c6b1..ea2ba93 100644 --- a/net/android/network_change_notifier_delegate_android.cc +++ b/net/android/network_change_notifier_delegate_android.cc @@ -4,6 +4,7 @@ #include "net/android/network_change_notifier_delegate_android.h" +#include "base/android/jni_array.h" #include "base/logging.h" #include "jni/NetworkChangeNotifier_jni.h" #include "net/android/network_change_notifier_android.h" @@ -44,6 +45,21 @@ NetworkChangeNotifier::ConnectionSubtype ConvertConnectionSubtype( } // namespace +// static +void NetworkChangeNotifierDelegateAndroid::JavaIntArrayToNetworkMap( + JNIEnv* env, + jintArray int_array, + NetworkMap* network_map) { + std::vector<int> int_list; + base::android::JavaIntArrayToIntVector(env, int_array, &int_list); + network_map->clear(); + for (auto i = int_list.begin(); i != int_list.end(); ++i) { + NetworkChangeNotifier::NetworkHandle network_handle = *i; + CHECK(++i != int_list.end()); + (*network_map)[network_handle] = static_cast<ConnectionType>(*i); + } +} + jdouble GetMaxBandwidthForConnectionSubtype(JNIEnv* env, const JavaParamRef<jclass>& caller, jint subtype) { @@ -67,6 +83,14 @@ NetworkChangeNotifierDelegateAndroid::NetworkChangeNotifierDelegateAndroid() SetCurrentMaxBandwidth( Java_NetworkChangeNotifier_getCurrentMaxBandwidthInMbps( env, java_network_change_notifier_.obj())); + SetCurrentDefaultNetwork(Java_NetworkChangeNotifier_getCurrentDefaultNetId( + env, java_network_change_notifier_.obj())); + NetworkMap network_map; + ScopedJavaLocalRef<jintArray> networks_and_types = + Java_NetworkChangeNotifier_getCurrentNetworksAndTypes( + env, java_network_change_notifier_.obj()); + JavaIntArrayToNetworkMap(env, networks_and_types.obj(), &network_map); + SetCurrentNetworksAndTypes(network_map); } NetworkChangeNotifierDelegateAndroid::~NetworkChangeNotifierDelegateAndroid() { @@ -93,14 +117,60 @@ void NetworkChangeNotifierDelegateAndroid:: *max_bandwidth_mbps = connection_max_bandwidth_; } +NetworkChangeNotifier::ConnectionType +NetworkChangeNotifierDelegateAndroid::GetNetworkConnectionType( + NetworkChangeNotifier::NetworkHandle network) const { + base::AutoLock auto_lock(connection_lock_); + auto network_entry = network_map_.find(network); + if (network_entry == network_map_.end()) + return ConnectionType::CONNECTION_UNKNOWN; + return network_entry->second; +} + +NetworkChangeNotifier::NetworkHandle +NetworkChangeNotifierDelegateAndroid::GetCurrentDefaultNetwork() const { + base::AutoLock auto_lock(connection_lock_); + return default_network_; +} + +void NetworkChangeNotifierDelegateAndroid::GetCurrentlyConnectedNetworks( + NetworkList* network_list) const { + network_list->clear(); + base::AutoLock auto_lock(connection_lock_); + for (auto i : network_map_) + network_list->push_back(i.first); +} + void NetworkChangeNotifierDelegateAndroid::NotifyConnectionTypeChanged( JNIEnv* env, jobject obj, - jint new_connection_type) { + jint new_connection_type, + jint default_netid) { DCHECK(thread_checker_.CalledOnValidThread()); const ConnectionType actual_connection_type = ConvertConnectionType( new_connection_type); SetCurrentConnectionType(actual_connection_type); + NetworkHandle default_network = default_netid; + if (default_network != GetCurrentDefaultNetwork()) { + SetCurrentDefaultNetwork(default_network); + bool default_exists; + { + base::AutoLock auto_lock(connection_lock_); + // |default_network| may be an invalid value (i.e. -1) in cases where + // the device is disconnected or when run on Android versions prior to L, + // in which case |default_exists| will correctly be false and no + // OnNetworkMadeDefault notification will be sent. + default_exists = network_map_.find(default_network) != network_map_.end(); + } + // Android Lollipop had race conditions where CONNECTIVITY_ACTION intents + // were sent out before the network was actually made the default. + // Delay sending the OnNetworkMadeDefault notification until we are + // actually notified that the network connected in NotifyOfNetworkConnect. + if (default_exists) { + observers_->Notify(FROM_HERE, &Observer::OnNetworkMadeDefault, + default_network); + } + } observers_->Notify(FROM_HERE, &Observer::OnConnectionTypeChanged); } @@ -121,6 +191,88 @@ void NetworkChangeNotifierDelegateAndroid::NotifyMaxBandwidthChanged( new_max_bandwidth, GetCurrentConnectionType()); } +void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkConnect( + JNIEnv* env, + jobject obj, + jint net_id, + jint connection_type) { + DCHECK(thread_checker_.CalledOnValidThread()); + NetworkHandle network = net_id; + bool already_exists; + { + base::AutoLock auto_lock(connection_lock_); + already_exists = network_map_.find(network) != network_map_.end(); + network_map_[network] = static_cast<ConnectionType>(connection_type); + } + // Android Lollipop would send many duplicate notifications. + // This was later fixed in Android Marshmallow. + // Deduplicate them here by avoiding sending duplicate notifications. + if (!already_exists) { + observers_->Notify(FROM_HERE, &Observer::OnNetworkConnected, network); + if (network == GetCurrentDefaultNetwork()) { + observers_->Notify(FROM_HERE, &Observer::OnNetworkMadeDefault, network); + } + } +} + +void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkSoonToDisconnect( + JNIEnv* env, + jobject obj, + jint net_id) { + DCHECK(thread_checker_.CalledOnValidThread()); + NetworkHandle network = net_id; + { + base::AutoLock auto_lock(connection_lock_); + if (network_map_.find(network) == network_map_.end()) + return; + } + observers_->Notify(FROM_HERE, &Observer::OnNetworkSoonToDisconnect, network); +} + +void NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkDisconnect( + JNIEnv* env, + jobject obj, + jint net_id) { + DCHECK(thread_checker_.CalledOnValidThread()); + NetworkHandle network = net_id; + { + base::AutoLock auto_lock(connection_lock_); + if (network == default_network_) + default_network_ = NetworkChangeNotifier::kInvalidNetworkHandle; + if (network_map_.erase(network) == 0) + return; + } + observers_->Notify(FROM_HERE, &Observer::OnNetworkDisconnected, network); +} + +void NetworkChangeNotifierDelegateAndroid::NotifyUpdateActiveNetworkList( + JNIEnv* env, + jobject obj, + jintArray active_networks) { + DCHECK(thread_checker_.CalledOnValidThread()); + NetworkList active_network_list; + base::android::JavaIntArrayToIntVector(env, active_networks, + &active_network_list); + NetworkList disconnected_networks; + { + base::AutoLock auto_lock(connection_lock_); + for (auto i : network_map_) { + bool found = false; + for (auto j : active_network_list) { + if (j == i.first) { + found = true; + break; + } + } + if (!found) { + disconnected_networks.push_back(i.first); + } + } + } + for (auto disconnected_network : disconnected_networks) + NotifyOfNetworkDisconnect(env, obj, disconnected_network); +} + void NetworkChangeNotifierDelegateAndroid::AddObserver( Observer* observer) { observers_->AddObserver(observer); @@ -148,6 +300,18 @@ void NetworkChangeNotifierDelegateAndroid::SetCurrentMaxBandwidth( connection_max_bandwidth_ = max_bandwidth; } +void NetworkChangeNotifierDelegateAndroid::SetCurrentDefaultNetwork( + NetworkHandle default_network) { + base::AutoLock auto_lock(connection_lock_); + default_network_ = default_network; +} + +void NetworkChangeNotifierDelegateAndroid::SetCurrentNetworksAndTypes( + NetworkMap network_map) { + base::AutoLock auto_lock(connection_lock_); + network_map_ = network_map; +} + void NetworkChangeNotifierDelegateAndroid::SetOnline() { JNIEnv* env = base::android::AttachCurrentThread(); Java_NetworkChangeNotifier_forceConnectivityState(env, true); @@ -158,4 +322,37 @@ void NetworkChangeNotifierDelegateAndroid::SetOffline() { Java_NetworkChangeNotifier_forceConnectivityState(env, false); } +void NetworkChangeNotifierDelegateAndroid::FakeNetworkConnected( + NetworkChangeNotifier::NetworkHandle network, + ConnectionType type) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_NetworkChangeNotifier_fakeNetworkConnected(env, network, type); +} + +void NetworkChangeNotifierDelegateAndroid::FakeNetworkSoonToBeDisconnected( + NetworkChangeNotifier::NetworkHandle network) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_NetworkChangeNotifier_fakeNetworkSoonToBeDisconnected(env, network); +} + +void NetworkChangeNotifierDelegateAndroid::FakeNetworkDisconnected( + NetworkChangeNotifier::NetworkHandle network) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_NetworkChangeNotifier_fakeNetworkDisconnected(env, network); +} + +void NetworkChangeNotifierDelegateAndroid::FakeUpdateActiveNetworkList( + NetworkChangeNotifier::NetworkList networks) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_NetworkChangeNotifier_fakeUpdateActiveNetworkList( + env, base::android::ToJavaIntArray(env, networks).obj()); +} + +void NetworkChangeNotifierDelegateAndroid::FakeDefaultNetwork( + NetworkChangeNotifier::NetworkHandle network, + ConnectionType type) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_NetworkChangeNotifier_fakeDefaultNetwork(env, network, type); +} + } // namespace net |