Index: talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc |
diff --git a/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc b/talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc |
index 1716c19cf8be84344a3ef1bff3f7bebf8a7d5647..27eb5427d38424544a87fab34951211784a925bc 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,39 @@ void AndroidNetworkMonitor::Stop() { |
jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); |
CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring"; |
- network_info_by_address_.clear(); |
+ network_info_by_handle_.clear(); |
+} |
+ |
+NetworkInformation* AndroidNetworkMonitor::GetNetworkInfoFromAddress( |
+ const rtc::IPAddress& address) { |
+ // Network handles (IDs) are created by the Android OS in the increasing |
pthatcher1
2016/01/30 02:22:07
in the increasing order => in increasing order
honghaiz3
2016/02/02 04:07:42
This is removed.
|
+ // order. By searching in the reverse direction, the one that was created most |
+ // recently is found first in the (unlikely) case that two handles have the |
+ // same IP address (e.g., caused by accidentally not deleting the old handle). |
+ auto& networks = network_info_by_handle_; |
+ auto it = std::find_if( |
+ networks.rbegin(), networks.rend(), |
+ [address](const std::pair<NetworkHandle, NetworkInformation>& pos) { |
pthatcher1
2016/01/30 02:22:07
"pos"? Why not "it" or "kv"?
honghaiz3
2016/02/02 04:07:42
This part is removed.
|
+ auto& addresses = pos.second.ip_addresses; |
+ return std::find(addresses.begin(), addresses.end(), address) != |
+ addresses.end(); |
+ }); |
pthatcher1
2016/01/30 02:22:07
Could we not have both a network_info_by_address_
honghaiz3
2016/02/02 04:07:42
Done.
honghaiz3
2016/02/02 17:44:13
Note, I used network_handle_by_address instead of
|
+ return (it != networks.rend()) ? &(it->second) : nullptr; |
} |
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_info_by_handle_| 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. |
+ NetworkInformation* network = GetNetworkInfoFromAddress(address); |
+ if (network == nullptr) { |
+ return rtc::NETWORK_BIND_ADDRESS_NOT_FOUND; |
+ } |
// NOTE: This does rely on Android implementation details, but |
// these details are unlikely to change. |
@@ -244,7 +285,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 +298,45 @@ 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<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) { |
- LOG(LS_INFO) << "Network available: " << network_info.ToString(); |
- for (rtc::IPAddress address : network_info.ip_addresses) { |
- network_info_by_address_[address] = network_info; |
+ network_info_by_handle_[network_info.handle] = network_info; |
+ adapter_type_by_name_[network_info.interface_name] = |
+ AdapterTypeFromNetworkType(network_info.type); |
+} |
+ |
+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) { |
+ network_info_by_handle_.erase(handle); |
pthatcher1
2016/01/30 02:22:07
You'd just need to do:
iter = network_info_by_han
honghaiz3
2016/02/02 04:07:42
Done.
|
+} |
+ |
+void AndroidNetworkMonitor::SetNetworkInfos( |
+ const std::vector<NetworkInformation>& network_infos) { |
+ RTC_CHECK(thread_checker_.CalledOnValidThread()); |
+ network_info_by_handle_.clear(); |
+ for (NetworkInformation network : network_infos) { |
+ OnNetworkConnected_w(network); |
} |
} |
+rtc::AdapterType AndroidNetworkMonitor::GetAdapterType( |
+ const std::string& if_name) { |
+ // If not found, the default type is 0 (ADAPTER_TYPE_UNKNOWN). |
+ return adapter_type_by_name_[if_name]; |
pthatcher1
2016/01/30 02:22:07
I think that's a little too subtle. Doing somethi
honghaiz3
2016/02/02 04:07:42
Done.
|
+} |
+ |
rtc::NetworkMonitorInterface* |
AndroidNetworkMonitorFactory::CreateNetworkMonitor() { |
return new AndroidNetworkMonitor(); |
@@ -283,6 +349,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<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)( |
JNIEnv* jni, jobject j_monitor, jlong j_native_monitor, |
jobject j_network_info) { |
@@ -290,7 +371,16 @@ JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)( |
reinterpret_cast<AndroidNetworkMonitor*>(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<AndroidNetworkMonitor*>(j_native_monitor); |
+ network_monitor->OnNetworkDisconnected( |
+ static_cast<NetworkHandle>(network_handle)); |
} |
} // namespace webrtc_jni |