#include "net/android/network_change_notifier_android.h"
#include <string>
#include <unordered_set>
#include "base/android/android_info.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/metrics/histogram_macros.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread.h"
#include "net/base/address_tracker_linux.h"
namespace net {
enum NetId {
INVALID = -1
};
class NetworkChangeNotifierAndroid::BlockingThreadObjects {
public:
BlockingThreadObjects()
: address_tracker_(
base::DoNothing(),
base::DoNothing(),
base::BindRepeating(NotifyNetworkChangeNotifierObservers),
std::unordered_set<std::string>()) {}
BlockingThreadObjects(const BlockingThreadObjects&) = delete;
BlockingThreadObjects& operator=(const BlockingThreadObjects&) = delete;
void Init() {
address_tracker_.Init();
}
static void NotifyNetworkChangeNotifierObservers() {
NetworkChangeNotifier::NotifyObserversOfIPAddressChange();
NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange();
}
private:
internal::AddressTrackerLinux address_tracker_;
};
NetworkChangeNotifierAndroid::~NetworkChangeNotifierAndroid() {
ClearGlobalPointer();
delegate_->UnregisterObserver(this);
}
NetworkChangeNotifier::ConnectionType
NetworkChangeNotifierAndroid::GetCurrentConnectionType() const {
return delegate_->GetCurrentConnectionType();
}
NetworkChangeNotifier::ConnectionCost
NetworkChangeNotifierAndroid::GetCurrentConnectionCost() {
return delegate_->GetCurrentConnectionCost();
}
NetworkChangeNotifier::ConnectionSubtype
NetworkChangeNotifierAndroid::GetCurrentConnectionSubtype() const {
return delegate_->GetCurrentConnectionSubtype();
}
void NetworkChangeNotifierAndroid::GetCurrentMaxBandwidthAndConnectionType(
double* max_bandwidth_mbps,
ConnectionType* connection_type) const {
delegate_->GetCurrentMaxBandwidthAndConnectionType(max_bandwidth_mbps,
connection_type);
}
void NetworkChangeNotifierAndroid::ForceNetworkHandlesSupportedForTesting() {
force_network_handles_supported_for_testing_ = true;
}
bool NetworkChangeNotifierAndroid::AreNetworkHandlesCurrentlySupported() const {
return force_network_handles_supported_for_testing_ ||
!delegate_->RegisterNetworkCallbackFailed();
}
void NetworkChangeNotifierAndroid::GetCurrentConnectedNetworks(
NetworkChangeNotifier::NetworkList* networks) const {
delegate_->GetCurrentlyConnectedNetworks(networks);
}
NetworkChangeNotifier::ConnectionType
NetworkChangeNotifierAndroid::GetCurrentNetworkConnectionType(
handles::NetworkHandle network) const {
return delegate_->GetNetworkConnectionType(network);
}
handles::NetworkHandle NetworkChangeNotifierAndroid::GetCurrentDefaultNetwork()
const {
return delegate_->GetCurrentDefaultNetwork();
}
void NetworkChangeNotifierAndroid::OnConnectionTypeChanged() {
BlockingThreadObjects::NotifyNetworkChangeNotifierObservers();
}
void NetworkChangeNotifierAndroid::OnConnectionCostChanged() {
NetworkChangeNotifier::NotifyObserversOfConnectionCostChange();
}
void NetworkChangeNotifierAndroid::OnMaxBandwidthChanged(
double max_bandwidth_mbps,
ConnectionType type) {
NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChange(max_bandwidth_mbps,
type);
}
void NetworkChangeNotifierAndroid::OnNetworkConnected(
handles::NetworkHandle network) {
NetworkChangeNotifier::NotifyObserversOfSpecificNetworkChange(
NetworkChangeType::kConnected, network);
}
void NetworkChangeNotifierAndroid::OnNetworkSoonToDisconnect(
handles::NetworkHandle network) {
NetworkChangeNotifier::NotifyObserversOfSpecificNetworkChange(
NetworkChangeType::kSoonToDisconnect, network);
}
void NetworkChangeNotifierAndroid::OnNetworkDisconnected(
handles::NetworkHandle network) {
NetworkChangeNotifier::NotifyObserversOfSpecificNetworkChange(
NetworkChangeType::kDisconnected, network);
}
void NetworkChangeNotifierAndroid::OnNetworkMadeDefault(
handles::NetworkHandle network) {
NetworkChangeNotifier::NotifyObserversOfSpecificNetworkChange(
NetworkChangeType::kMadeDefault, network);
}
void NetworkChangeNotifierAndroid::OnDefaultNetworkActive() {
NetworkChangeNotifier::NotifyObserversOfDefaultNetworkActive();
}
NetworkChangeNotifierAndroid::NetworkChangeNotifierAndroid(
NetworkChangeNotifierDelegateAndroid* delegate)
: NetworkChangeNotifier(NetworkChangeCalculatorParamsAndroid()),
delegate_(delegate),
blocking_thread_objects_(nullptr, base::OnTaskRunnerDeleter(nullptr)) {
static_assert(NetId::INVALID == handles::kInvalidNetworkHandle,
"handles::kInvalidNetworkHandle doesn't match NetId::INVALID");
delegate_->RegisterObserver(this);
if (base::android::android_info::sdk_int() <
base::android::android_info::SDK_VERSION_P) {
scoped_refptr<base::SequencedTaskRunner> blocking_thread_runner =
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
blocking_thread_objects_ =
std::unique_ptr<BlockingThreadObjects, base::OnTaskRunnerDeleter>(
new BlockingThreadObjects(),
base::OnTaskRunnerDeleter(blocking_thread_runner));
blocking_thread_runner->PostTask(
FROM_HERE,
base::BindOnce(&BlockingThreadObjects::Init,
base::Unretained(blocking_thread_objects_.get())));
}
}
NetworkChangeNotifier::NetworkChangeCalculatorParams
NetworkChangeNotifierAndroid::NetworkChangeCalculatorParamsAndroid() {
NetworkChangeCalculatorParams params;
params.ip_address_offline_delay_ = base::Seconds(1);
params.ip_address_online_delay_ = base::Seconds(1);
params.connection_type_offline_delay_ = base::Seconds(0);
params.connection_type_online_delay_ = base::Seconds(0);
return params;
}
bool NetworkChangeNotifierAndroid::IsDefaultNetworkActiveInternal() {
return delegate_->IsDefaultNetworkActive();
}
void NetworkChangeNotifierAndroid::DefaultNetworkActiveObserverAdded() {
delegate_->DefaultNetworkActiveObserverAdded();
}
void NetworkChangeNotifierAndroid::DefaultNetworkActiveObserverRemoved() {
delegate_->DefaultNetworkActiveObserverRemoved();
}
}