Get the adapter type information from Android OS.

BUG=

Review URL: https://codereview.webrtc.org/1594673002

Cr-Commit-Position: refs/heads/master@{#11463}
This commit is contained in:
honghaiz 2016-02-02 12:54:14 -08:00 committed by Commit bot
parent ae695e95a6
commit a7ad7c3ca0
9 changed files with 293 additions and 79 deletions

View File

@ -142,6 +142,9 @@ public class NetworkMonitorTest extends ActivityTestCase {
@Override @Override
public void onNetworkConnect(NetworkInformation networkInfo) {} public void onNetworkConnect(NetworkInformation networkInfo) {}
@Override
public void onNetworkDisconnect(int networkHandle) {}
} }
private static final Object lock = new Object(); private static final Object lock = new Object();

View File

@ -154,19 +154,27 @@ public class NetworkMonitor {
if (autoDetector == null) { if (autoDetector == null) {
autoDetector = new NetworkMonitorAutoDetect( autoDetector = new NetworkMonitorAutoDetect(
new NetworkMonitorAutoDetect.Observer() { new NetworkMonitorAutoDetect.Observer() {
@Override @Override
public void onConnectionTypeChanged(ConnectionType newConnectionType) { public void onConnectionTypeChanged(ConnectionType newConnectionType) {
updateCurrentConnectionType(newConnectionType); updateCurrentConnectionType(newConnectionType);
} }
@Override @Override
public void onNetworkConnect(NetworkInformation networkInfo) { public void onNetworkConnect(NetworkInformation networkInfo) {
updateNetworkInformation(networkInfo); notifyObserversOfNetworkConnect(networkInfo);
}
@Override
public void onNetworkDisconnect(int networkHandle) {
notifyObserversOfNetworkDisconnect(networkHandle);
} }
}, },
applicationContext); applicationContext);
final NetworkMonitorAutoDetect.NetworkState networkState = final NetworkMonitorAutoDetect.NetworkState networkState =
autoDetector.getCurrentNetworkState(); autoDetector.getCurrentNetworkState();
updateCurrentConnectionType(autoDetector.getConnectionType(networkState)); 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) { for (long nativeObserver : nativeNetworkObservers) {
nativeNotifyOfNetworkConnect(nativeObserver, networkInfo); 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. * Adds an observer for any connection type changes.
*/ */
@ -224,11 +248,11 @@ public class NetworkMonitor {
&& connectionType != ConnectionType.CONNECTION_NONE; && connectionType != ConnectionType.CONNECTION_NONE;
} }
private native long nativeCreateNetworkMonitor();
private native void nativeNotifyConnectionTypeChanged(long nativePtr); private native void nativeNotifyConnectionTypeChanged(long nativePtr);
private native void nativeNotifyOfNetworkConnect(long nativePtr, NetworkInformation networkInfo); 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. // For testing only.
static void resetInstanceForTests(Context context) { static void resetInstanceForTests(Context context) {

View File

@ -28,6 +28,8 @@
package org.webrtc; package org.webrtc;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import org.webrtc.Logging; import org.webrtc.Logging;
@ -120,6 +122,54 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
return subtype; 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. */ /** Queries the ConnectivityManager for information about the current connection. */
static class ConnectivityManagerDelegate { static class ConnectivityManagerDelegate {
@ -128,7 +178,6 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
* gracefully below. * gracefully below.
*/ */
private final ConnectivityManager connectivityManager; private final ConnectivityManager connectivityManager;
private NetworkCallback networkCallback;
ConnectivityManagerDelegate(Context context) { ConnectivityManagerDelegate(Context context) {
connectivityManager = connectivityManager =
@ -186,6 +235,18 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
return connectivityManager.getAllNetworks(); 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 * Returns the NetID of the current default network. Returns
* INVALID_NET_ID if no current default network connected. * INVALID_NET_ID if no current default network connected.
@ -193,7 +254,7 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
*/ */
@SuppressLint("NewApi") @SuppressLint("NewApi")
int getDefaultNetId() { int getDefaultNetId() {
if (connectivityManager == null) { if (!supportNetworkCallback()) {
return INVALID_NET_ID; return INVALID_NET_ID;
} }
// Android Lollipop had no API to get the default network; only an // Android Lollipop had no API to get the default network; only an
@ -226,6 +287,17 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
return defaultNetId; 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 * Returns true if {@code network} can provide Internet access. Can be used to
* ignore specialized networks (e.g. IMS, FOTA). * ignore specialized networks (e.g. IMS, FOTA).
@ -240,30 +312,19 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
return capabilities != null && capabilities.hasCapability(NET_CAPABILITY_INTERNET); return capabilities != null && capabilities.hasCapability(NET_CAPABILITY_INTERNET);
} }
/** Only callable on Lollipop and newer releases. */
@SuppressLint("NewApi") @SuppressLint("NewApi")
public void requestMobileNetwork(final Observer observer) { public void registerNetworkCallback(NetworkCallback networkCallback) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || connectivityManager.registerNetworkCallback(
connectivityManager == null) { new NetworkRequest.Builder().addCapability(NET_CAPABILITY_INTERNET).build(),
return; networkCallback);
} }
networkCallback = new NetworkCallback() {
@Override /** Only callable on Lollipop and newer releases. */
public void onAvailable(Network network) { @SuppressLint("NewApi")
super.onAvailable(network); public void requestMobileNetwork(NetworkCallback networkCallback) {
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");
NetworkRequest.Builder builder = new NetworkRequest.Builder(); NetworkRequest.Builder builder = new NetworkRequest.Builder();
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); builder.addCapability(NET_CAPABILITY_INTERNET).addTransportType(TRANSPORT_CELLULAR);
builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
connectivityManager.requestNetwork(builder.build(), networkCallback); connectivityManager.requestNetwork(builder.build(), networkCallback);
} }
@ -279,15 +340,16 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
} }
@SuppressLint("NewApi") @SuppressLint("NewApi")
public void releaseCallback() { public void releaseCallback(NetworkCallback networkCallback) {
if (networkCallback != null) { if (supportNetworkCallback()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Logging.d(TAG, "Unregister network callback");
connectivityManager.unregisterNetworkCallback(networkCallback); connectivityManager.unregisterNetworkCallback(networkCallback);
} }
networkCallback = null;
}
} }
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; static final int INVALID_NET_ID = -1;
private static final String TAG = "NetworkMonitorAutoDetect"; private static final String TAG = "NetworkMonitorAutoDetect";
private final IntentFilter intentFilter;
// Observer for the connection type change. // Observer for the connection type change.
private final Observer observer; private final Observer observer;
private final IntentFilter intentFilter;
private final Context context; 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 ConnectivityManagerDelegate connectivityManagerDelegate;
private WifiManagerDelegate wifiManagerDelegate; private WifiManagerDelegate wifiManagerDelegate;
private boolean isRegistered; private boolean isRegistered;
private ConnectionType connectionType; private ConnectionType connectionType;
private String wifiSSID; private String wifiSSID;
@ -345,11 +412,13 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
*/ */
public void onConnectionTypeChanged(ConnectionType newConnectionType); public void onConnectionTypeChanged(ConnectionType newConnectionType);
public void onNetworkConnect(NetworkInformation networkInfo); public void onNetworkConnect(NetworkInformation networkInfo);
public void onNetworkDisconnect(int networkHandle);
} }
/** /**
* Constructs a NetworkMonitorAutoDetect. Should only be called on UI thread. * Constructs a NetworkMonitorAutoDetect. Should only be called on UI thread.
*/ */
@SuppressLint("NewApi")
public NetworkMonitorAutoDetect(Observer observer, Context context) { public NetworkMonitorAutoDetect(Observer observer, Context context) {
this.observer = observer; this.observer = observer;
this.context = context; this.context = context;
@ -360,7 +429,17 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
connectionType = getConnectionType(networkState); connectionType = getConnectionType(networkState);
wifiSSID = getWifiSSID(networkState); wifiSSID = getWifiSSID(networkState);
intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(); 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; return isRegistered;
} }
NetworkInformation[] getActiveNetworkList() {
return connectivityManagerDelegate.getActiveNetworkList();
}
public void destroy() { public void destroy() {
if (allNetworkCallback != null) {
connectivityManagerDelegate.releaseCallback(allNetworkCallback);
}
if (mobileNetworkCallback != null) {
connectivityManagerDelegate.releaseCallback(mobileNetworkCallback);
}
unregisterReceiver(); unregisterReceiver();
} }
@ -393,22 +482,20 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
* Registers a BroadcastReceiver in the given context. * Registers a BroadcastReceiver in the given context.
*/ */
private void registerReceiver() { private void registerReceiver() {
if (!isRegistered) { if (isRegistered) return;
isRegistered = true; isRegistered = true;
context.registerReceiver(this, intentFilter); context.registerReceiver(this, intentFilter);
connectivityManagerDelegate.requestMobileNetwork(observer);
}
} }
/** /**
* Unregisters the BroadcastReceiver in the given context. * Unregisters the BroadcastReceiver in the given context.
*/ */
private void unregisterReceiver() { private void unregisterReceiver() {
if (isRegistered) { if (!isRegistered) return;
isRegistered = false; isRegistered = false;
context.unregisterReceiver(this); context.unregisterReceiver(this);
connectivityManagerDelegate.releaseCallback();
}
} }
public NetworkState getCurrentNetworkState() { public NetworkState getCurrentNetworkState() {
@ -422,9 +509,6 @@ public class NetworkMonitorAutoDetect extends BroadcastReceiver {
* when not implemented. * when not implemented.
*/ */
public int getDefaultNetId() { public int getDefaultNetId() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return INVALID_NET_ID;
}
return connectivityManagerDelegate.getDefaultNetId(); return connectivityManagerDelegate.getDefaultNetId();
} }

View File

@ -71,6 +71,29 @@ static NetworkType GetNetworkTypeFromJava(JNIEnv* jni, jobject j_network_type) {
return NetworkType::NETWORK_UNKNOWN; 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) { static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) {
jclass j_ip_address_class = GetObjectClass(jni, 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"); jfieldID j_address_id = GetFieldID(jni, j_ip_address_class, "address", "[B");
@ -186,7 +209,7 @@ void AndroidNetworkMonitor::Start() {
jmethodID m = jmethodID m =
GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V"); GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V");
jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.startMonitoring"; CHECK_EXCEPTION(jni()) << "Error during CallVoidMethod";
} }
void AndroidNetworkMonitor::Stop() { void AndroidNetworkMonitor::Stop() {
@ -207,21 +230,24 @@ void AndroidNetworkMonitor::Stop() {
jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring"; 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, int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd,
const rtc::IPAddress& address) { const rtc::IPAddress& address) {
RTC_CHECK(thread_checker_.CalledOnValidThread()); 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 // Android prior to Lollipop didn't have support for binding sockets to
// networks. However, in that case it should not have reached here because // 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. // 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 // NOTE: This does rely on Android implementation details, but
// these details are unlikely to change. // these details are unlikely to change.
@ -244,7 +270,7 @@ int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd,
LOG(LS_ERROR) << "Symbol setNetworkForSocket not found "; LOG(LS_ERROR) << "Symbol setNetworkForSocket not found ";
return rtc::NETWORK_BIND_NOT_IMPLEMENTED; 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 // If |network| has since disconnected, |rv| will be ENONET. Surface this as
// ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
// the less descriptive ERR_FAILED. // the less descriptive ERR_FAILED.
@ -257,20 +283,58 @@ int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd,
return rtc::NETWORK_BIND_FAILURE; return rtc::NETWORK_BIND_FAILURE;
} }
void AndroidNetworkMonitor::OnNetworkAvailable( void AndroidNetworkMonitor::OnNetworkConnected(
const NetworkInformation& network_info) { const NetworkInformation& network_info) {
LOG(LS_INFO) << "Network connected: " << network_info.ToString();
worker_thread()->Invoke<void>(rtc::Bind( worker_thread()->Invoke<void>(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) { const NetworkInformation& network_info) {
LOG(LS_INFO) << "Network available: " << network_info.ToString(); adapter_type_by_name_[network_info.interface_name] =
for (rtc::IPAddress address : network_info.ip_addresses) { AdapterTypeFromNetworkType(network_info.type);
network_info_by_address_[address] = network_info; 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<void>(
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<NetworkInformation>& 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* rtc::NetworkMonitorInterface*
AndroidNetworkMonitorFactory::CreateNetworkMonitor() { AndroidNetworkMonitorFactory::CreateNetworkMonitor() {
return new AndroidNetworkMonitor(); return new AndroidNetworkMonitor();
@ -283,6 +347,21 @@ JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)(
network_monitor->OnNetworksChanged(); 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<AndroidNetworkMonitor*>(j_native_monitor);
std::vector<NetworkInformation> 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)( JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)(
JNIEnv* jni, jobject j_monitor, jlong j_native_monitor, JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
jobject j_network_info) { jobject j_network_info) {
@ -290,7 +369,16 @@ JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)(
reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor); reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
NetworkInformation network_info = NetworkInformation network_info =
GetNetworkInformationFromJava(jni, j_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<AndroidNetworkMonitor*>(j_native_monitor);
network_monitor->OnNetworkDisconnected(
static_cast<NetworkHandle>(network_handle));
} }
} // namespace webrtc_jni } // namespace webrtc_jni

View File

@ -75,19 +75,25 @@ class AndroidNetworkMonitor : public rtc::NetworkMonitorBase,
int BindSocketToNetwork(int socket_fd, int BindSocketToNetwork(int socket_fd,
const rtc::IPAddress& address) override; 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<NetworkInformation>& network_infos);
private: private:
JNIEnv* jni() { return AttachCurrentThreadIfNeeded(); } 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<jclass> j_network_monitor_class_; ScopedGlobalRef<jclass> j_network_monitor_class_;
ScopedGlobalRef<jobject> j_network_monitor_; ScopedGlobalRef<jobject> j_network_monitor_;
rtc::ThreadChecker thread_checker_; rtc::ThreadChecker thread_checker_;
static jobject application_context_; static jobject application_context_;
bool started_ = false; bool started_ = false;
std::map<rtc::IPAddress, NetworkInformation> network_info_by_address_; std::map<std::string, rtc::AdapterType> adapter_type_by_name_;
std::map<rtc::IPAddress, NetworkHandle> network_handle_by_address_;
std::map<NetworkHandle, NetworkInformation> network_info_by_handle_;
}; };
class AndroidNetworkMonitorFactory : public rtc::NetworkMonitorFactory { class AndroidNetworkMonitorFactory : public rtc::NetworkMonitorFactory {

View File

@ -441,6 +441,8 @@ void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces,
AdapterType adapter_type = ADAPTER_TYPE_UNKNOWN; AdapterType adapter_type = ADAPTER_TYPE_UNKNOWN;
if (cursor->ifa_flags & IFF_LOOPBACK) { if (cursor->ifa_flags & IFF_LOOPBACK) {
adapter_type = ADAPTER_TYPE_LOOPBACK; adapter_type = ADAPTER_TYPE_LOOPBACK;
} else if (network_monitor_) {
adapter_type = network_monitor_->GetAdapterType(cursor->ifa_name);
} }
#if defined(WEBRTC_IOS) #if defined(WEBRTC_IOS)
// Cell networks are pdp_ipN on iOS. // Cell networks are pdp_ipN on iOS.

View File

@ -18,6 +18,7 @@
#include "webrtc/base/basictypes.h" #include "webrtc/base/basictypes.h"
#include "webrtc/base/ipaddress.h" #include "webrtc/base/ipaddress.h"
#include "webrtc/base/networkmonitor.h"
#include "webrtc/base/messagehandler.h" #include "webrtc/base/messagehandler.h"
#include "webrtc/base/scoped_ptr.h" #include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/sigslot.h" #include "webrtc/base/sigslot.h"
@ -36,15 +37,6 @@ class Network;
class NetworkMonitorInterface; class NetworkMonitorInterface;
class Thread; 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. // By default, ignore loopback interfaces on the host.
const int kDefaultNetworkIgnoreMask = ADAPTER_TYPE_LOOPBACK; const int kDefaultNetworkIgnoreMask = ADAPTER_TYPE_LOOPBACK;

View File

@ -32,6 +32,9 @@ class FakeNetworkMonitor : public NetworkMonitorBase {
void Start() override { started_ = true; } void Start() override { started_ = true; }
void Stop() override { started_ = false; } void Stop() override { started_ = false; }
bool started() { return started_; } bool started() { return started_; }
AdapterType GetAdapterType(const std::string& if_name) override {
return ADAPTER_TYPE_UNKNOWN;
}
private: private:
bool started_ = false; bool started_ = false;

View File

@ -29,6 +29,16 @@ enum NetworkBindingResults {
NETWORK_BIND_NETWORK_CHANGED = -4 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 { class NetworkBinderInterface {
public: public:
// Binds a socket to the network that is attached to |address| so that all // 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, // Implementations should call this method on the base when networks change,
// and the base will fire SignalNetworksChanged on the right thread. // and the base will fire SignalNetworksChanged on the right thread.
virtual void OnNetworksChanged() = 0; virtual void OnNetworksChanged() = 0;
virtual AdapterType GetAdapterType(const std::string& interface_name) = 0;
}; };
class NetworkMonitorBase : public NetworkMonitorInterface, class NetworkMonitorBase : public NetworkMonitorInterface,