From a7ad7c3ca0de9e997af5cae35a76556575413b6a Mon Sep 17 00:00:00 2001 From: honghaiz Date: Tue, 2 Feb 2016 12:54:14 -0800 Subject: [PATCH] Get the adapter type information from Android OS. BUG= Review URL: https://codereview.webrtc.org/1594673002 Cr-Commit-Position: refs/heads/master@{#11463} --- .../src/org/webrtc/NetworkMonitorTest.java | 3 + .../android/org/webrtc/NetworkMonitor.java | 34 +++- .../org/webrtc/NetworkMonitorAutoDetect.java | 176 +++++++++++++----- .../java/jni/androidnetworkmonitor_jni.cc | 120 ++++++++++-- .../java/jni/androidnetworkmonitor_jni.h | 12 +- webrtc/base/network.cc | 2 + webrtc/base/network.h | 10 +- webrtc/base/network_unittest.cc | 3 + webrtc/base/networkmonitor.h | 12 ++ 9 files changed, 293 insertions(+), 79 deletions(-) diff --git a/talk/app/webrtc/androidtests/src/org/webrtc/NetworkMonitorTest.java b/talk/app/webrtc/androidtests/src/org/webrtc/NetworkMonitorTest.java index 8c0a794ea0..3bdbbddb78 100644 --- a/talk/app/webrtc/androidtests/src/org/webrtc/NetworkMonitorTest.java +++ b/talk/app/webrtc/androidtests/src/org/webrtc/NetworkMonitorTest.java @@ -142,6 +142,9 @@ public class NetworkMonitorTest extends ActivityTestCase { @Override public void onNetworkConnect(NetworkInformation networkInfo) {} + + @Override + public void onNetworkDisconnect(int networkHandle) {} } private static final Object lock = new Object(); diff --git a/talk/app/webrtc/java/android/org/webrtc/NetworkMonitor.java b/talk/app/webrtc/java/android/org/webrtc/NetworkMonitor.java index 0f3df42fbd..427070efad 100644 --- a/talk/app/webrtc/java/android/org/webrtc/NetworkMonitor.java +++ b/talk/app/webrtc/java/android/org/webrtc/NetworkMonitor.java @@ -154,19 +154,27 @@ public class NetworkMonitor { if (autoDetector == null) { autoDetector = new NetworkMonitorAutoDetect( new NetworkMonitorAutoDetect.Observer() { + @Override public void onConnectionTypeChanged(ConnectionType newConnectionType) { updateCurrentConnectionType(newConnectionType); } + @Override public void onNetworkConnect(NetworkInformation networkInfo) { - updateNetworkInformation(networkInfo); + notifyObserversOfNetworkConnect(networkInfo); + } + + @Override + public void onNetworkDisconnect(int networkHandle) { + notifyObserversOfNetworkDisconnect(networkHandle); } }, applicationContext); final NetworkMonitorAutoDetect.NetworkState networkState = autoDetector.getCurrentNetworkState(); updateCurrentConnectionType(autoDetector.getConnectionType(networkState)); + updateActiveNetworkList(); } } @@ -187,12 +195,28 @@ public class NetworkMonitor { } } - private void updateNetworkInformation(NetworkInformation networkInfo) { + private void notifyObserversOfNetworkConnect(NetworkInformation networkInfo) { for (long nativeObserver : nativeNetworkObservers) { nativeNotifyOfNetworkConnect(nativeObserver, networkInfo); } } + private void notifyObserversOfNetworkDisconnect(int networkHandle) { + for (long nativeObserver : nativeNetworkObservers) { + nativeNotifyOfNetworkDisconnect(nativeObserver, networkHandle); + } + } + + private void updateActiveNetworkList() { + NetworkInformation[] networkInfos = autoDetector.getActiveNetworkList(); + if (networkInfos.length == 0) { + return; + } + for (long nativeObserver : nativeNetworkObservers) { + nativeNotifyOfActiveNetworkList(nativeObserver, networkInfos); + } + } + /** * Adds an observer for any connection type changes. */ @@ -224,11 +248,11 @@ public class NetworkMonitor { && connectionType != ConnectionType.CONNECTION_NONE; } - private native long nativeCreateNetworkMonitor(); - private native void nativeNotifyConnectionTypeChanged(long nativePtr); - private native void nativeNotifyOfNetworkConnect(long nativePtr, NetworkInformation networkInfo); + private native void nativeNotifyOfNetworkDisconnect(long nativePtr, int networkHandle); + private native void nativeNotifyOfActiveNetworkList(long nativePtr, + NetworkInformation[] networkInfos); // For testing only. static void resetInstanceForTests(Context context) { diff --git a/talk/app/webrtc/java/android/org/webrtc/NetworkMonitorAutoDetect.java b/talk/app/webrtc/java/android/org/webrtc/NetworkMonitorAutoDetect.java index baadd279a5..e3d6d0cef6 100644 --- a/talk/app/webrtc/java/android/org/webrtc/NetworkMonitorAutoDetect.java +++ b/talk/app/webrtc/java/android/org/webrtc/NetworkMonitorAutoDetect.java @@ -28,6 +28,8 @@ package org.webrtc; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; + import org.webrtc.Logging; @@ -120,6 +122,54 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { return subtype; } } + /** + * The methods in this class get called when the network changes if the callback + * is registered with a proper network request. It is only available in Android Lollipop + * and above. + */ + @SuppressLint("NewApi") + private class SimpleNetworkCallback extends NetworkCallback { + + @Override + public void onAvailable(Network network) { + NetworkInformation networkInformation = connectivityManagerDelegate.networkToInfo(network); + Logging.d(TAG, "Network " + networkInformation.name + " with handle " + + networkInformation.handle + " is connected "); + observer.onNetworkConnect(networkInformation); + } + + @Override + public void onCapabilitiesChanged( + Network network, NetworkCapabilities networkCapabilities) { + // A capabilities change may indicate the ConnectionType has changed, + // so forward the new NetworkInformation along to observer. + NetworkInformation networkInformation = connectivityManagerDelegate.networkToInfo(network); + observer.onNetworkConnect(networkInformation); + } + + @Override + public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { + // A link property change may indicate the IP address changes. + // so forward the new NetworkInformation to the observer. + NetworkInformation networkInformation = connectivityManagerDelegate.networkToInfo(network); + observer.onNetworkConnect(networkInformation); + } + + @Override + public void onLosing(Network network, int maxMsToLive) { + // Tell the network is going to lose in MaxMsToLive milliseconds. + // We may use this signal later. + Logging.d(TAG, "Network with handle " + networkToNetId(network) + + " is about to lose in " + maxMsToLive + "ms"); + } + + @Override + public void onLost(Network network) { + int handle = networkToNetId(network); + Logging.d(TAG, "Network with handle " + handle + " is disconnected"); + observer.onNetworkDisconnect(handle); + } + } /** Queries the ConnectivityManager for information about the current connection. */ static class ConnectivityManagerDelegate { @@ -128,7 +178,6 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { * gracefully below. */ private final ConnectivityManager connectivityManager; - private NetworkCallback networkCallback; ConnectivityManagerDelegate(Context context) { connectivityManager = @@ -186,6 +235,18 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { return connectivityManager.getAllNetworks(); } + NetworkInformation[] getActiveNetworkList() { + if (!supportNetworkCallback()) { + return new NetworkInformation[0]; + } + Network[] networks = getAllNetworks(); + NetworkInformation[] netInfos = new NetworkInformation[networks.length]; + for (int i = 0; i < networks.length; ++i) { + netInfos[i] = networkToInfo(networks[i]); + } + return netInfos; + } + /** * Returns the NetID of the current default network. Returns * INVALID_NET_ID if no current default network connected. @@ -193,7 +254,7 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { */ @SuppressLint("NewApi") int getDefaultNetId() { - if (connectivityManager == null) { + if (!supportNetworkCallback()) { return INVALID_NET_ID; } // Android Lollipop had no API to get the default network; only an @@ -226,6 +287,17 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { return defaultNetId; } + @SuppressLint("NewApi") + private NetworkInformation networkToInfo(Network network) { + LinkProperties linkProperties = connectivityManager.getLinkProperties(network); + NetworkInformation networkInformation = new NetworkInformation( + linkProperties.getInterfaceName(), + getConnectionType(getNetworkState(network)), + networkToNetId(network), + getIPAddresses(linkProperties)); + return networkInformation; + } + /** * Returns true if {@code network} can provide Internet access. Can be used to * ignore specialized networks (e.g. IMS, FOTA). @@ -240,30 +312,19 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { return capabilities != null && capabilities.hasCapability(NET_CAPABILITY_INTERNET); } + /** Only callable on Lollipop and newer releases. */ @SuppressLint("NewApi") - public void requestMobileNetwork(final Observer observer) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || - connectivityManager == null) { - return; - } - networkCallback = new NetworkCallback() { - @Override - public void onAvailable(Network network) { - super.onAvailable(network); - LinkProperties linkProperties = connectivityManager.getLinkProperties(network); - NetworkInformation networkInformation = new NetworkInformation( - linkProperties.getInterfaceName(), - getConnectionType(getNetworkState(network)), - networkToNetId(network), - getIPAddresses(linkProperties)); - Logging.d(TAG, "Network " + networkInformation.name + " is connected "); - observer.onNetworkConnect(networkInformation); - } - }; - Logging.d(TAG, "Requesting cellular network"); + public void registerNetworkCallback(NetworkCallback networkCallback) { + connectivityManager.registerNetworkCallback( + new NetworkRequest.Builder().addCapability(NET_CAPABILITY_INTERNET).build(), + networkCallback); + } + + /** Only callable on Lollipop and newer releases. */ + @SuppressLint("NewApi") + public void requestMobileNetwork(NetworkCallback networkCallback) { NetworkRequest.Builder builder = new NetworkRequest.Builder(); - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); + builder.addCapability(NET_CAPABILITY_INTERNET).addTransportType(TRANSPORT_CELLULAR); connectivityManager.requestNetwork(builder.build(), networkCallback); } @@ -279,15 +340,16 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { } @SuppressLint("NewApi") - public void releaseCallback() { - if (networkCallback != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - connectivityManager.unregisterNetworkCallback(networkCallback); - } - networkCallback = null; + public void releaseCallback(NetworkCallback networkCallback) { + if (supportNetworkCallback()) { + Logging.d(TAG, "Unregister network callback"); + connectivityManager.unregisterNetworkCallback(networkCallback); } } + public boolean supportNetworkCallback() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && connectivityManager != null; + } } @@ -323,15 +385,20 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { static final int INVALID_NET_ID = -1; private static final String TAG = "NetworkMonitorAutoDetect"; - private final IntentFilter intentFilter; // Observer for the connection type change. private final Observer observer; - + private final IntentFilter intentFilter; private final Context context; - // connectivityManagerDelegates and wifiManagerDelegate are only non-final for testing. + // Used to request mobile network. It does not do anything except for keeping + // the callback for releasing the request. + private final NetworkCallback mobileNetworkCallback; + // Used to receive updates on all networks. + private final NetworkCallback allNetworkCallback; + // connectivityManagerDelegate and wifiManagerDelegate are only non-final for testing. private ConnectivityManagerDelegate connectivityManagerDelegate; private WifiManagerDelegate wifiManagerDelegate; + private boolean isRegistered; private ConnectionType connectionType; private String wifiSSID; @@ -345,11 +412,13 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { */ public void onConnectionTypeChanged(ConnectionType newConnectionType); public void onNetworkConnect(NetworkInformation networkInfo); + public void onNetworkDisconnect(int networkHandle); } /** * Constructs a NetworkMonitorAutoDetect. Should only be called on UI thread. */ + @SuppressLint("NewApi") public NetworkMonitorAutoDetect(Observer observer, Context context) { this.observer = observer; this.context = context; @@ -360,7 +429,17 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { connectionType = getConnectionType(networkState); wifiSSID = getWifiSSID(networkState); intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); + registerReceiver(); + if (connectivityManagerDelegate.supportNetworkCallback()) { + mobileNetworkCallback = new NetworkCallback(); + connectivityManagerDelegate.requestMobileNetwork(mobileNetworkCallback); + allNetworkCallback = new SimpleNetworkCallback(); + connectivityManagerDelegate.registerNetworkCallback(allNetworkCallback); + } else { + mobileNetworkCallback = null; + allNetworkCallback = null; + } } /** @@ -385,7 +464,17 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { return isRegistered; } + NetworkInformation[] getActiveNetworkList() { + return connectivityManagerDelegate.getActiveNetworkList(); + } + public void destroy() { + if (allNetworkCallback != null) { + connectivityManagerDelegate.releaseCallback(allNetworkCallback); + } + if (mobileNetworkCallback != null) { + connectivityManagerDelegate.releaseCallback(mobileNetworkCallback); + } unregisterReceiver(); } @@ -393,22 +482,20 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { * Registers a BroadcastReceiver in the given context. */ private void registerReceiver() { - if (!isRegistered) { - isRegistered = true; - context.registerReceiver(this, intentFilter); - connectivityManagerDelegate.requestMobileNetwork(observer); - } + if (isRegistered) return; + + isRegistered = true; + context.registerReceiver(this, intentFilter); } /** * Unregisters the BroadcastReceiver in the given context. */ private void unregisterReceiver() { - if (isRegistered) { - isRegistered = false; - context.unregisterReceiver(this); - connectivityManagerDelegate.releaseCallback(); - } + if (!isRegistered) return; + + isRegistered = false; + context.unregisterReceiver(this); } public NetworkState getCurrentNetworkState() { @@ -422,9 +509,6 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver { * when not implemented. */ public int getDefaultNetId() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return INVALID_NET_ID; - } return connectivityManagerDelegate.getDefaultNetId(); } diff --git a/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc b/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc index 1716c19cf8..ca0c7821d5 100644 --- a/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc +++ b/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc @@ -71,6 +71,29 @@ static NetworkType GetNetworkTypeFromJava(JNIEnv* jni, jobject j_network_type) { return NetworkType::NETWORK_UNKNOWN; } +static rtc::AdapterType AdapterTypeFromNetworkType(NetworkType network_type) { + switch (network_type) { + case NETWORK_UNKNOWN: + RTC_DCHECK(false) << "Unknown network type "; + return rtc::ADAPTER_TYPE_UNKNOWN; + case NETWORK_ETHERNET: + return rtc::ADAPTER_TYPE_ETHERNET; + case NETWORK_WIFI: + return rtc::ADAPTER_TYPE_WIFI; + case NETWORK_4G: + case NETWORK_3G: + case NETWORK_2G: + return rtc::ADAPTER_TYPE_CELLULAR; + case NETWORK_BLUETOOTH: + // There is no corresponding mapping for bluetooth networks. + // Map it to VPN for now. + return rtc::ADAPTER_TYPE_VPN; + default: + RTC_DCHECK(false) << "Invalid network type " << network_type; + return rtc::ADAPTER_TYPE_UNKNOWN; + } +} + static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) { jclass j_ip_address_class = GetObjectClass(jni, j_ip_address); jfieldID j_address_id = GetFieldID(jni, j_ip_address_class, "address", "[B"); @@ -186,7 +209,7 @@ void AndroidNetworkMonitor::Start() { jmethodID m = GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V"); jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); - CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.startMonitoring"; + CHECK_EXCEPTION(jni()) << "Error during CallVoidMethod"; } void AndroidNetworkMonitor::Stop() { @@ -207,21 +230,24 @@ void AndroidNetworkMonitor::Stop() { jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring"; - network_info_by_address_.clear(); + network_handle_by_address_.clear(); + network_info_by_handle_.clear(); } int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd, const rtc::IPAddress& address) { RTC_CHECK(thread_checker_.CalledOnValidThread()); - auto it = network_info_by_address_.find(address); - if (it == network_info_by_address_.end()) { - return rtc::NETWORK_BIND_ADDRESS_NOT_FOUND; - } // Android prior to Lollipop didn't have support for binding sockets to // networks. However, in that case it should not have reached here because - // |network_info_by_address_| should only be populated in Android Lollipop + // |network_handle_by_address_| should only be populated in Android Lollipop // and above. - NetworkInformation network = it->second; + // TODO(honghaiz): Add a check for Android version here so that it won't try + // to look for handle if the Android version is before Lollipop. + auto iter = network_handle_by_address_.find(address); + if (iter == network_handle_by_address_.end()) { + return rtc::NETWORK_BIND_ADDRESS_NOT_FOUND; + } + NetworkHandle network_handle = iter->second; // NOTE: This does rely on Android implementation details, but // these details are unlikely to change. @@ -244,7 +270,7 @@ int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd, LOG(LS_ERROR) << "Symbol setNetworkForSocket not found "; return rtc::NETWORK_BIND_NOT_IMPLEMENTED; } - int rv = setNetworkForSocket(network.handle, socket_fd); + int rv = setNetworkForSocket(network_handle, socket_fd); // If |network| has since disconnected, |rv| will be ENONET. Surface this as // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back // the less descriptive ERR_FAILED. @@ -257,20 +283,58 @@ int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd, return rtc::NETWORK_BIND_FAILURE; } -void AndroidNetworkMonitor::OnNetworkAvailable( +void AndroidNetworkMonitor::OnNetworkConnected( const NetworkInformation& network_info) { + LOG(LS_INFO) << "Network connected: " << network_info.ToString(); worker_thread()->Invoke(rtc::Bind( - &AndroidNetworkMonitor::OnNetworkAvailable_w, this, network_info)); + &AndroidNetworkMonitor::OnNetworkConnected_w, this, network_info)); } -void AndroidNetworkMonitor::OnNetworkAvailable_w( +void AndroidNetworkMonitor::OnNetworkConnected_w( const NetworkInformation& network_info) { - LOG(LS_INFO) << "Network available: " << network_info.ToString(); - for (rtc::IPAddress address : network_info.ip_addresses) { - network_info_by_address_[address] = network_info; + adapter_type_by_name_[network_info.interface_name] = + AdapterTypeFromNetworkType(network_info.type); + network_info_by_handle_[network_info.handle] = network_info; + for (const rtc::IPAddress& address : network_info.ip_addresses) { + network_handle_by_address_[address] = network_info.handle; } } +void AndroidNetworkMonitor::OnNetworkDisconnected(NetworkHandle handle) { + LOG(LS_INFO) << "Network disconnected for handle " << handle; + worker_thread()->Invoke( + rtc::Bind(&AndroidNetworkMonitor::OnNetworkDisconnected_w, this, handle)); +} + +void AndroidNetworkMonitor::OnNetworkDisconnected_w(NetworkHandle handle) { + auto iter = network_info_by_handle_.find(handle); + if (iter != network_info_by_handle_.end()) { + for (const rtc::IPAddress& address : iter->second.ip_addresses) { + network_handle_by_address_.erase(address); + } + network_info_by_handle_.erase(iter); + } +} + +void AndroidNetworkMonitor::SetNetworkInfos( + const std::vector& network_infos) { + RTC_CHECK(thread_checker_.CalledOnValidThread()); + network_handle_by_address_.clear(); + network_info_by_handle_.clear(); + for (NetworkInformation network : network_infos) { + OnNetworkConnected_w(network); + } +} + +rtc::AdapterType AndroidNetworkMonitor::GetAdapterType( + const std::string& if_name) { + auto iter = adapter_type_by_name_.find(if_name); + if (iter == adapter_type_by_name_.end()) { + return rtc::ADAPTER_TYPE_UNKNOWN; + } + return iter->second; +} + rtc::NetworkMonitorInterface* AndroidNetworkMonitorFactory::CreateNetworkMonitor() { return new AndroidNetworkMonitor(); @@ -283,6 +347,21 @@ JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)( network_monitor->OnNetworksChanged(); } +JOW(void, NetworkMonitor_nativeNotifyOfActiveNetworkList)( + JNIEnv* jni, jobject j_monitor, jlong j_native_monitor, + jobjectArray j_network_infos) { + AndroidNetworkMonitor* network_monitor = + reinterpret_cast(j_native_monitor); + std::vector network_infos; + size_t num_networks = jni->GetArrayLength(j_network_infos); + for (size_t i = 0; i < num_networks; ++i) { + jobject j_network_info = jni->GetObjectArrayElement(j_network_infos, i); + CHECK_EXCEPTION(jni) << "Error during GetObjectArrayElement"; + network_infos.push_back(GetNetworkInformationFromJava(jni, j_network_info)); + } + network_monitor->SetNetworkInfos(network_infos); +} + JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)( JNIEnv* jni, jobject j_monitor, jlong j_native_monitor, jobject j_network_info) { @@ -290,7 +369,16 @@ JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)( reinterpret_cast(j_native_monitor); NetworkInformation network_info = GetNetworkInformationFromJava(jni, j_network_info); - network_monitor->OnNetworkAvailable(network_info); + network_monitor->OnNetworkConnected(network_info); +} + +JOW(void, NetworkMonitor_nativeNotifyOfNetworkDisconnect)( + JNIEnv* jni, jobject j_monitor, jlong j_native_monitor, + jint network_handle) { + AndroidNetworkMonitor* network_monitor = + reinterpret_cast(j_native_monitor); + network_monitor->OnNetworkDisconnected( + static_cast(network_handle)); } } // namespace webrtc_jni diff --git a/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h b/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h index 17de3603c6..a5c8490173 100644 --- a/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h +++ b/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h @@ -75,19 +75,25 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorBase, int BindSocketToNetwork(int socket_fd, const rtc::IPAddress& address) override; - void OnNetworkAvailable(const NetworkInformation& network_info); + rtc::AdapterType GetAdapterType(const std::string& if_name) override; + void OnNetworkConnected(const NetworkInformation& network_info); + void OnNetworkDisconnected(NetworkHandle network_handle); + void SetNetworkInfos(const std::vector& network_infos); private: JNIEnv* jni() { return AttachCurrentThreadIfNeeded(); } - void OnNetworkAvailable_w(const NetworkInformation& network_info); + void OnNetworkConnected_w(const NetworkInformation& network_info); + void OnNetworkDisconnected_w(NetworkHandle network_handle); ScopedGlobalRef j_network_monitor_class_; ScopedGlobalRef j_network_monitor_; rtc::ThreadChecker thread_checker_; static jobject application_context_; bool started_ = false; - std::map network_info_by_address_; + std::map adapter_type_by_name_; + std::map network_handle_by_address_; + std::map network_info_by_handle_; }; class AndroidNetworkMonitorFactory : public rtc::NetworkMonitorFactory { diff --git a/webrtc/base/network.cc b/webrtc/base/network.cc index 3c38e5bce4..6b04f891a1 100644 --- a/webrtc/base/network.cc +++ b/webrtc/base/network.cc @@ -441,6 +441,8 @@ void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces, AdapterType adapter_type = ADAPTER_TYPE_UNKNOWN; if (cursor->ifa_flags & IFF_LOOPBACK) { adapter_type = ADAPTER_TYPE_LOOPBACK; + } else if (network_monitor_) { + adapter_type = network_monitor_->GetAdapterType(cursor->ifa_name); } #if defined(WEBRTC_IOS) // Cell networks are pdp_ipN on iOS. diff --git a/webrtc/base/network.h b/webrtc/base/network.h index 2f2e1b3a45..10ce6f0e01 100644 --- a/webrtc/base/network.h +++ b/webrtc/base/network.h @@ -18,6 +18,7 @@ #include "webrtc/base/basictypes.h" #include "webrtc/base/ipaddress.h" +#include "webrtc/base/networkmonitor.h" #include "webrtc/base/messagehandler.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/base/sigslot.h" @@ -36,15 +37,6 @@ class Network; class NetworkMonitorInterface; class Thread; -enum AdapterType { - // This enum resembles the one in Chromium net::ConnectionType. - ADAPTER_TYPE_UNKNOWN = 0, - ADAPTER_TYPE_ETHERNET = 1 << 0, - ADAPTER_TYPE_WIFI = 1 << 1, - ADAPTER_TYPE_CELLULAR = 1 << 2, - ADAPTER_TYPE_VPN = 1 << 3, - ADAPTER_TYPE_LOOPBACK = 1 << 4 -}; // By default, ignore loopback interfaces on the host. const int kDefaultNetworkIgnoreMask = ADAPTER_TYPE_LOOPBACK; diff --git a/webrtc/base/network_unittest.cc b/webrtc/base/network_unittest.cc index 43ccb34c28..0f7d6db8ff 100644 --- a/webrtc/base/network_unittest.cc +++ b/webrtc/base/network_unittest.cc @@ -32,6 +32,9 @@ class FakeNetworkMonitor : public NetworkMonitorBase { void Start() override { started_ = true; } void Stop() override { started_ = false; } bool started() { return started_; } + AdapterType GetAdapterType(const std::string& if_name) override { + return ADAPTER_TYPE_UNKNOWN; + } private: bool started_ = false; diff --git a/webrtc/base/networkmonitor.h b/webrtc/base/networkmonitor.h index dd15f6e8f7..d9d6cc49d8 100644 --- a/webrtc/base/networkmonitor.h +++ b/webrtc/base/networkmonitor.h @@ -29,6 +29,16 @@ enum NetworkBindingResults { NETWORK_BIND_NETWORK_CHANGED = -4 }; +enum AdapterType { + // This enum resembles the one in Chromium net::ConnectionType. + ADAPTER_TYPE_UNKNOWN = 0, + ADAPTER_TYPE_ETHERNET = 1 << 0, + ADAPTER_TYPE_WIFI = 1 << 1, + ADAPTER_TYPE_CELLULAR = 1 << 2, + ADAPTER_TYPE_VPN = 1 << 3, + ADAPTER_TYPE_LOOPBACK = 1 << 4 +}; + class NetworkBinderInterface { public: // Binds a socket to the network that is attached to |address| so that all @@ -70,6 +80,8 @@ class NetworkMonitorInterface { // Implementations should call this method on the base when networks change, // and the base will fire SignalNetworksChanged on the right thread. virtual void OnNetworksChanged() = 0; + + virtual AdapterType GetAdapterType(const std::string& interface_name) = 0; }; class NetworkMonitorBase : public NetworkMonitorInterface,