Add a new interface for creating a udp socket in which it binds the socket to a network if the network handle is set.
Plus, in stunport, turnport and allocation sequence, create a socket using the new interface.
BUG=
Review URL: https://codereview.webrtc.org/1556743002
Cr-Commit-Position: refs/heads/master@{#11279}
diff --git a/talk/app/webrtc/java/android/org/webrtc/NetworkMonitor.java b/talk/app/webrtc/java/android/org/webrtc/NetworkMonitor.java
index 581a223..0f3df42 100644
--- a/talk/app/webrtc/java/android/org/webrtc/NetworkMonitor.java
+++ b/talk/app/webrtc/java/android/org/webrtc/NetworkMonitor.java
@@ -29,9 +29,11 @@
import static org.webrtc.NetworkMonitorAutoDetect.ConnectionType;
import static org.webrtc.NetworkMonitorAutoDetect.INVALID_NET_ID;
+import static org.webrtc.NetworkMonitorAutoDetect.NetworkInformation;
+
+import org.webrtc.Logging;
import android.content.Context;
-import android.util.Log;
import java.util.ArrayList;
@@ -117,14 +119,14 @@
// Called by the native code.
private void startMonitoring(long nativeObserver) {
- Log.d(TAG, "Start monitoring from native observer " + nativeObserver);
+ Logging.d(TAG, "Start monitoring from native observer " + nativeObserver);
nativeNetworkObservers.add(nativeObserver);
setAutoDetectConnectivityStateInternal(true);
}
// Called by the native code.
private void stopMonitoring(long nativeObserver) {
- Log.d(TAG, "Stop monitoring from native observer " + nativeObserver);
+ Logging.d(TAG, "Stop monitoring from native observer " + nativeObserver);
setAutoDetectConnectivityStateInternal(false);
nativeNetworkObservers.remove(nativeObserver);
}
@@ -156,11 +158,15 @@
public void onConnectionTypeChanged(ConnectionType newConnectionType) {
updateCurrentConnectionType(newConnectionType);
}
+ @Override
+ public void onNetworkConnect(NetworkInformation networkInfo) {
+ updateNetworkInformation(networkInfo);
+ }
},
applicationContext);
final NetworkMonitorAutoDetect.NetworkState networkState =
autoDetector.getCurrentNetworkState();
- updateCurrentConnectionType(autoDetector.getCurrentConnectionType(networkState));
+ updateCurrentConnectionType(autoDetector.getConnectionType(networkState));
}
}
@@ -181,6 +187,12 @@
}
}
+ private void updateNetworkInformation(NetworkInformation networkInfo) {
+ for (long nativeObserver : nativeNetworkObservers) {
+ nativeNotifyOfNetworkConnect(nativeObserver, networkInfo);
+ }
+ }
+
/**
* Adds an observer for any connection type changes.
*/
@@ -216,6 +228,8 @@
private native void nativeNotifyConnectionTypeChanged(long nativePtr);
+ private native void nativeNotifyOfNetworkConnect(long nativePtr, NetworkInformation networkInfo);
+
// For testing only.
static void resetInstanceForTests(Context context) {
instance = new NetworkMonitor(context);
diff --git a/talk/app/webrtc/java/android/org/webrtc/NetworkMonitorAutoDetect.java b/talk/app/webrtc/java/android/org/webrtc/NetworkMonitorAutoDetect.java
index 950dcdf..baadd27 100644
--- a/talk/app/webrtc/java/android/org/webrtc/NetworkMonitorAutoDetect.java
+++ b/talk/app/webrtc/java/android/org/webrtc/NetworkMonitorAutoDetect.java
@@ -29,6 +29,8 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import org.webrtc.Logging;
+
import android.Manifest.permission;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
@@ -37,14 +39,17 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.net.NetworkRequest;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.telephony.TelephonyManager;
-import android.util.Log;
/**
* Borrowed from Chromium's
@@ -66,6 +71,28 @@
CONNECTION_NONE
}
+ public static class IPAddress {
+ public final byte[] address;
+ public IPAddress (byte[] address) {
+ this.address = address;
+ }
+ }
+
+ /** Java version of NetworkMonitor.NetworkInformation */
+ public static class NetworkInformation{
+ public final String name;
+ public final ConnectionType type;
+ public final int handle;
+ public final IPAddress[] ipAddresses;
+ public NetworkInformation(String name, ConnectionType type, int handle,
+ IPAddress[] addresses) {
+ this.name = name;
+ this.type = type;
+ this.handle = handle;
+ this.ipAddresses = addresses;
+ }
+ };
+
static class NetworkState {
private final boolean connected;
// Defined from ConnectivityManager.TYPE_XXX for non-mobile; for mobile, it is
@@ -101,6 +128,7 @@
* gracefully below.
*/
private final ConnectivityManager connectivityManager;
+ private NetworkCallback networkCallback;
ConnectivityManagerDelegate(Context context) {
connectivityManager =
@@ -211,30 +239,69 @@
connectivityManager.getNetworkCapabilities(network);
return capabilities != null && capabilities.hasCapability(NET_CAPABILITY_INTERNET);
}
+
+ @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");
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ connectivityManager.requestNetwork(builder.build(), networkCallback);
+ }
+
+ @SuppressLint("NewApi")
+ IPAddress[] getIPAddresses(LinkProperties linkProperties) {
+ IPAddress[] ipAddresses = new IPAddress[linkProperties.getLinkAddresses().size()];
+ int i = 0;
+ for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
+ ipAddresses[i] = new IPAddress(linkAddress.getAddress().getAddress());
+ ++i;
+ }
+ return ipAddresses;
+ }
+
+ @SuppressLint("NewApi")
+ public void releaseCallback() {
+ if (networkCallback != null) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ connectivityManager.unregisterNetworkCallback(networkCallback);
+ }
+ networkCallback = null;
+ }
+ }
+
}
+
/** Queries the WifiManager for SSID of the current Wifi connection. */
static class WifiManagerDelegate {
private final Context context;
- private final WifiManager wifiManager;
- private final boolean hasWifiPermission;
-
WifiManagerDelegate(Context context) {
this.context = context;
-
- hasWifiPermission = context.getPackageManager().checkPermission(
- permission.ACCESS_WIFI_STATE, context.getPackageName())
- == PackageManager.PERMISSION_GRANTED;
- wifiManager = hasWifiPermission
- ? (WifiManager) context.getSystemService(Context.WIFI_SERVICE) : null;
}
// For testing.
WifiManagerDelegate() {
// All the methods below should be overridden.
context = null;
- wifiManager = null;
- hasWifiPermission = false;
}
String getWifiSSID() {
@@ -252,9 +319,6 @@
return "";
}
- boolean getHasWifiPermission() {
- return hasWifiPermission;
- }
}
static final int INVALID_NET_ID = -1;
@@ -280,6 +344,7 @@
* Called when default network changes.
*/
public void onConnectionTypeChanged(ConnectionType newConnectionType);
+ public void onNetworkConnect(NetworkInformation networkInfo);
}
/**
@@ -292,8 +357,8 @@
wifiManagerDelegate = new WifiManagerDelegate(context);
final NetworkState networkState = connectivityManagerDelegate.getNetworkState();
- connectionType = getCurrentConnectionType(networkState);
- wifiSSID = getCurrentWifiSSID(networkState);
+ connectionType = getConnectionType(networkState);
+ wifiSSID = getWifiSSID(networkState);
intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver();
}
@@ -331,6 +396,7 @@
if (!isRegistered) {
isRegistered = true;
context.registerReceiver(this, intentFilter);
+ connectivityManagerDelegate.requestMobileNetwork(observer);
}
}
@@ -341,6 +407,7 @@
if (isRegistered) {
isRegistered = false;
context.unregisterReceiver(this);
+ connectivityManagerDelegate.releaseCallback();
}
}
@@ -361,7 +428,7 @@
return connectivityManagerDelegate.getDefaultNetId();
}
- public ConnectionType getCurrentConnectionType(NetworkState networkState) {
+ public static ConnectionType getConnectionType(NetworkState networkState) {
if (!networkState.isConnected()) {
return ConnectionType.CONNECTION_NONE;
}
@@ -404,8 +471,8 @@
}
}
- private String getCurrentWifiSSID(NetworkState networkState) {
- if (getCurrentConnectionType(networkState) != ConnectionType.CONNECTION_WIFI) return "";
+ private String getWifiSSID(NetworkState networkState) {
+ if (getConnectionType(networkState) != ConnectionType.CONNECTION_WIFI) return "";
return wifiManagerDelegate.getWifiSSID();
}
@@ -419,13 +486,13 @@
}
private void connectionTypeChanged(NetworkState networkState) {
- ConnectionType newConnectionType = getCurrentConnectionType(networkState);
- String newWifiSSID = getCurrentWifiSSID(networkState);
+ ConnectionType newConnectionType = getConnectionType(networkState);
+ String newWifiSSID = getWifiSSID(networkState);
if (newConnectionType == connectionType && newWifiSSID.equals(wifiSSID)) return;
connectionType = newConnectionType;
wifiSSID = newWifiSSID;
- Log.d(TAG, "Network connectivity changed, type is: " + connectionType);
+ Logging.d(TAG, "Network connectivity changed, type is: " + connectionType);
observer.onConnectionTypeChanged(newConnectionType);
}
diff --git a/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc b/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc
index f7a8c07..1716c19 100644
--- a/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc
+++ b/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc
@@ -27,13 +27,125 @@
#include "talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h"
+#include <dlfcn.h>
+
+#include "webrtc/base/bind.h"
#include "webrtc/base/common.h"
+#include "webrtc/base/ipaddress.h"
#include "talk/app/webrtc/java/jni/classreferenceholder.h"
#include "talk/app/webrtc/java/jni/jni_helpers.h"
namespace webrtc_jni {
+
jobject AndroidNetworkMonitor::application_context_ = nullptr;
+static NetworkType GetNetworkTypeFromJava(JNIEnv* jni, jobject j_network_type) {
+ std::string enum_name =
+ GetJavaEnumName(jni, "org/webrtc/NetworkMonitorAutoDetect$ConnectionType",
+ j_network_type);
+ if (enum_name == "CONNECTION_UNKNOWN") {
+ return NetworkType::NETWORK_UNKNOWN;
+ }
+ if (enum_name == "CONNECTION_ETHERNET") {
+ return NetworkType::NETWORK_ETHERNET;
+ }
+ if (enum_name == "CONNECTION_WIFI") {
+ return NetworkType::NETWORK_WIFI;
+ }
+ if (enum_name == "CONNECTION_4G") {
+ return NetworkType::NETWORK_4G;
+ }
+ if (enum_name == "CONNECTION_3G") {
+ return NetworkType::NETWORK_3G;
+ }
+ if (enum_name == "CONNECTION_2G") {
+ return NetworkType::NETWORK_2G;
+ }
+ if (enum_name == "CONNECTION_BLUETOOTH") {
+ return NetworkType::NETWORK_BLUETOOTH;
+ }
+ if (enum_name == "CONNECTION_NONE") {
+ return NetworkType::NETWORK_NONE;
+ }
+ ASSERT(false);
+ return NetworkType::NETWORK_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");
+ jbyteArray j_addresses =
+ static_cast<jbyteArray>(GetObjectField(jni, j_ip_address, j_address_id));
+ size_t address_length = jni->GetArrayLength(j_addresses);
+ jbyte* addr_array = jni->GetByteArrayElements(j_addresses, nullptr);
+ CHECK_EXCEPTION(jni) << "Error during GetIPAddressFromJava";
+ if (address_length == 4) {
+ // IP4
+ struct in_addr ip4_addr;
+ memcpy(&ip4_addr.s_addr, addr_array, 4);
+ jni->ReleaseByteArrayElements(j_addresses, addr_array, JNI_ABORT);
+ return rtc::IPAddress(ip4_addr);
+ }
+ // IP6
+ RTC_CHECK(address_length == 16);
+ struct in6_addr ip6_addr;
+ memcpy(ip6_addr.s6_addr, addr_array, address_length);
+ jni->ReleaseByteArrayElements(j_addresses, addr_array, JNI_ABORT);
+ return rtc::IPAddress(ip6_addr);
+}
+
+static void GetIPAddressesFromJava(JNIEnv* jni,
+ jobjectArray j_ip_addresses,
+ std::vector<rtc::IPAddress>* ip_addresses) {
+ ip_addresses->clear();
+ size_t num_addresses = jni->GetArrayLength(j_ip_addresses);
+ CHECK_EXCEPTION(jni) << "Error during GetArrayLength";
+ for (size_t i = 0; i < num_addresses; ++i) {
+ jobject j_ip_address = jni->GetObjectArrayElement(j_ip_addresses, i);
+ CHECK_EXCEPTION(jni) << "Error during GetObjectArrayElement";
+ rtc::IPAddress ip = GetIPAddressFromJava(jni, j_ip_address);
+ ip_addresses->push_back(ip);
+ }
+}
+
+static NetworkInformation GetNetworkInformationFromJava(
+ JNIEnv* jni,
+ jobject j_network_info) {
+ jclass j_network_info_class = GetObjectClass(jni, j_network_info);
+ jfieldID j_interface_name_id =
+ GetFieldID(jni, j_network_info_class, "name", "Ljava/lang/String;");
+ jfieldID j_handle_id = GetFieldID(jni, j_network_info_class, "handle", "I");
+ jfieldID j_type_id =
+ GetFieldID(jni, j_network_info_class, "type",
+ "Lorg/webrtc/NetworkMonitorAutoDetect$ConnectionType;");
+ jfieldID j_ip_addresses_id =
+ GetFieldID(jni, j_network_info_class, "ipAddresses",
+ "[Lorg/webrtc/NetworkMonitorAutoDetect$IPAddress;");
+
+ NetworkInformation network_info;
+ network_info.interface_name = JavaToStdString(
+ jni, GetStringField(jni, j_network_info, j_interface_name_id));
+ network_info.handle =
+ static_cast<NetworkHandle>(GetIntField(jni, j_network_info, j_handle_id));
+ network_info.type = GetNetworkTypeFromJava(
+ jni, GetObjectField(jni, j_network_info, j_type_id));
+ jobjectArray j_ip_addresses = static_cast<jobjectArray>(
+ GetObjectField(jni, j_network_info, j_ip_addresses_id));
+ GetIPAddressesFromJava(jni, j_ip_addresses, &network_info.ip_addresses);
+ return network_info;
+}
+
+std::string NetworkInformation::ToString() const {
+ std::stringstream ss;
+ ss << "NetInfo[name " << interface_name << "; handle " << handle << "; type "
+ << type << "; address";
+ for (const rtc::IPAddress address : ip_addresses) {
+ ss << " " << address.ToString();
+ }
+ ss << "]";
+ return ss.str();
+}
+
// static
void AndroidNetworkMonitor::SetAndroidContext(JNIEnv* jni, jobject context) {
if (application_context_) {
@@ -61,6 +173,16 @@
void AndroidNetworkMonitor::Start() {
RTC_CHECK(thread_checker_.CalledOnValidThread());
+ if (started_) {
+ return;
+ }
+ started_ = true;
+
+ // This is kind of magic behavior, but doing this allows the SocketServer to
+ // use this as a NetworkBinder to bind sockets on a particular network when
+ // it creates sockets.
+ worker_thread()->socketserver()->set_network_binder(this);
+
jmethodID m =
GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V");
jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
@@ -69,10 +191,89 @@
void AndroidNetworkMonitor::Stop() {
RTC_CHECK(thread_checker_.CalledOnValidThread());
+ if (!started_) {
+ return;
+ }
+ started_ = false;
+
+ // Once the network monitor stops, it will clear all network information and
+ // it won't find the network handle to bind anyway.
+ if (worker_thread()->socketserver()->network_binder() == this) {
+ worker_thread()->socketserver()->set_network_binder(nullptr);
+ }
+
jmethodID m =
GetMethodID(jni(), *j_network_monitor_class_, "stopMonitoring", "(J)V");
jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring";
+
+ network_info_by_address_.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
+ // and above.
+ NetworkInformation network = it->second;
+
+ // NOTE: This does rely on Android implementation details, but
+ // these details are unlikely to change.
+ typedef int (*SetNetworkForSocket)(unsigned netId, int socketFd);
+ static SetNetworkForSocket setNetworkForSocket;
+ // This is not threadsafe, but we are running this only on the worker thread.
+ if (setNetworkForSocket == nullptr) {
+ // Android's netd client library should always be loaded in our address
+ // space as it shims libc functions like connect().
+ const std::string net_library_path = "libnetd_client.so";
+ void* lib = dlopen(net_library_path.c_str(), RTLD_LAZY);
+ if (lib == nullptr) {
+ LOG(LS_ERROR) << "Library " << net_library_path << " not found!";
+ return rtc::NETWORK_BIND_NOT_IMPLEMENTED;
+ }
+ setNetworkForSocket = reinterpret_cast<SetNetworkForSocket>(
+ dlsym(lib, "setNetworkForSocket"));
+ }
+ if (setNetworkForSocket == nullptr) {
+ LOG(LS_ERROR) << "Symbol setNetworkForSocket not found ";
+ return rtc::NETWORK_BIND_NOT_IMPLEMENTED;
+ }
+ 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.
+ if (rv == 0) {
+ return rtc::NETWORK_BIND_SUCCESS;
+ }
+ if (rv == ENONET) {
+ return rtc::NETWORK_BIND_NETWORK_CHANGED;
+ }
+ return rtc::NETWORK_BIND_FAILURE;
+}
+
+void AndroidNetworkMonitor::OnNetworkAvailable(
+ const NetworkInformation& network_info) {
+ worker_thread()->Invoke<void>(rtc::Bind(
+ &AndroidNetworkMonitor::OnNetworkAvailable_w, this, network_info));
+}
+
+void AndroidNetworkMonitor::OnNetworkAvailable_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;
+ }
+}
+
+rtc::NetworkMonitorInterface*
+AndroidNetworkMonitorFactory::CreateNetworkMonitor() {
+ return new AndroidNetworkMonitor();
}
JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)(
@@ -82,4 +283,14 @@
network_monitor->OnNetworksChanged();
}
+JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)(
+ JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
+ jobject j_network_info) {
+ AndroidNetworkMonitor* network_monitor =
+ reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
+ NetworkInformation network_info =
+ GetNetworkInformationFromJava(jni, j_network_info);
+ network_monitor->OnNetworkAvailable(network_info);
+}
+
} // namespace webrtc_jni
diff --git a/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h b/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h
index 3f5110c..17de360 100644
--- a/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h
+++ b/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h
@@ -30,12 +30,41 @@
#include "webrtc/base/networkmonitor.h"
+#include <map>
+
+#include "webrtc/base/basictypes.h"
#include "webrtc/base/thread_checker.h"
#include "talk/app/webrtc/java/jni/jni_helpers.h"
namespace webrtc_jni {
-class AndroidNetworkMonitor : public rtc::NetworkMonitorBase {
+typedef uint32_t NetworkHandle;
+
+// c++ equivalent of java NetworkMonitorAutoDetect.ConnectionType.
+enum NetworkType {
+ NETWORK_UNKNOWN,
+ NETWORK_ETHERNET,
+ NETWORK_WIFI,
+ NETWORK_4G,
+ NETWORK_3G,
+ NETWORK_2G,
+ NETWORK_BLUETOOTH,
+ NETWORK_NONE
+};
+
+// The information is collected from Android OS so that the native code can get
+// the network type and handle (Android network ID) for each interface.
+struct NetworkInformation {
+ std::string interface_name;
+ NetworkHandle handle;
+ NetworkType type;
+ std::vector<rtc::IPAddress> ip_addresses;
+
+ std::string ToString() const;
+};
+
+class AndroidNetworkMonitor : public rtc::NetworkMonitorBase,
+ public rtc::NetworkBinderInterface {
public:
AndroidNetworkMonitor();
@@ -44,22 +73,28 @@
void Start() override;
void Stop() override;
+ int BindSocketToNetwork(int socket_fd,
+ const rtc::IPAddress& address) override;
+ void OnNetworkAvailable(const NetworkInformation& network_info);
+
private:
JNIEnv* jni() { return AttachCurrentThreadIfNeeded(); }
+ void OnNetworkAvailable_w(const NetworkInformation& network_info);
+
ScopedGlobalRef<jclass> j_network_monitor_class_;
ScopedGlobalRef<jobject> j_network_monitor_;
rtc::ThreadChecker thread_checker_;
static jobject application_context_;
+ bool started_ = false;
+ std::map<rtc::IPAddress, NetworkInformation> network_info_by_address_;
};
class AndroidNetworkMonitorFactory : public rtc::NetworkMonitorFactory {
public:
AndroidNetworkMonitorFactory() {}
- rtc::NetworkMonitorInterface* CreateNetworkMonitor() override {
- return new AndroidNetworkMonitor();
- }
+ rtc::NetworkMonitorInterface* CreateNetworkMonitor() override;
};
} // namespace webrtc_jni
diff --git a/talk/app/webrtc/java/jni/classreferenceholder.cc b/talk/app/webrtc/java/jni/classreferenceholder.cc
index 5fe8ec7..a7d36c2 100644
--- a/talk/app/webrtc/java/jni/classreferenceholder.cc
+++ b/talk/app/webrtc/java/jni/classreferenceholder.cc
@@ -81,6 +81,9 @@
LoadClass(jni, "org/webrtc/EglBase$Context");
LoadClass(jni, "org/webrtc/EglBase14$Context");
LoadClass(jni, "org/webrtc/NetworkMonitor");
+ LoadClass(jni, "org/webrtc/NetworkMonitorAutoDetect$ConnectionType");
+ LoadClass(jni, "org/webrtc/NetworkMonitorAutoDetect$IPAddress");
+ LoadClass(jni, "org/webrtc/NetworkMonitorAutoDetect$NetworkInformation");
LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder");
LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo");
LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder$VideoCodecType");
diff --git a/talk/app/webrtc/java/jni/jni_helpers.cc b/talk/app/webrtc/java/jni/jni_helpers.cc
index 3a7ff21..25b340f 100644
--- a/talk/app/webrtc/java/jni/jni_helpers.cc
+++ b/talk/app/webrtc/java/jni/jni_helpers.cc
@@ -27,6 +27,8 @@
*/
#include "talk/app/webrtc/java/jni/jni_helpers.h"
+#include "talk/app/webrtc/java/jni/classreferenceholder.h"
+
#include <asm/unistd.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
@@ -256,6 +258,19 @@
return ret;
}
+std::string GetJavaEnumName(JNIEnv* jni,
+ const std::string& className,
+ jobject j_enum) {
+ jclass enumClass = FindClass(jni, className.c_str());
+ jmethodID nameMethod =
+ GetMethodID(jni, enumClass, "name", "()Ljava/lang/String;");
+ jstring name =
+ reinterpret_cast<jstring>(jni->CallObjectMethod(j_enum, nameMethod));
+ CHECK_EXCEPTION(jni) << "error during CallObjectMethod for " << className
+ << ".name";
+ return JavaToStdString(jni, name);
+}
+
jobject NewGlobalRef(JNIEnv* jni, jobject o) {
jobject ret = jni->NewGlobalRef(o);
CHECK_EXCEPTION(jni) << "error during NewGlobalRef";
diff --git a/talk/app/webrtc/java/jni/jni_helpers.h b/talk/app/webrtc/java/jni/jni_helpers.h
index 7072ee8..374962b 100644
--- a/talk/app/webrtc/java/jni/jni_helpers.h
+++ b/talk/app/webrtc/java/jni/jni_helpers.h
@@ -104,6 +104,11 @@
jobject JavaEnumFromIndex(JNIEnv* jni, jclass state_class,
const std::string& state_class_name, int index);
+// Returns the name of a Java enum.
+std::string GetJavaEnumName(JNIEnv* jni,
+ const std::string& className,
+ jobject j_enum);
+
jobject NewGlobalRef(JNIEnv* jni, jobject o);
void DeleteGlobalRef(JNIEnv* jni, jobject o);
diff --git a/talk/app/webrtc/java/jni/peerconnection_jni.cc b/talk/app/webrtc/java/jni/peerconnection_jni.cc
index f80f576..6059623 100644
--- a/talk/app/webrtc/java/jni/peerconnection_jni.cc
+++ b/talk/app/webrtc/java/jni/peerconnection_jni.cc
@@ -1395,18 +1395,6 @@
#endif
}
-static std::string
-GetJavaEnumName(JNIEnv* jni, const std::string& className, jobject j_enum) {
- jclass enumClass = FindClass(jni, className.c_str());
- jmethodID nameMethod =
- GetMethodID(jni, enumClass, "name", "()Ljava/lang/String;");
- jstring name =
- reinterpret_cast<jstring>(jni->CallObjectMethod(j_enum, nameMethod));
- CHECK_EXCEPTION(jni) << "error during CallObjectMethod for "
- << className << ".name";
- return JavaToStdString(jni, name);
-}
-
static PeerConnectionInterface::IceTransportsType
JavaIceTransportsTypeToNativeType(JNIEnv* jni, jobject j_ice_transports_type) {
std::string enum_name = GetJavaEnumName(