Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: talk/app/webrtc/java/jni/androidnetworkmonitor_jni.cc

Issue 1594673002: Get the adapter type information from Android OS. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fix an indentation error Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h ('k') | webrtc/base/network.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2015 Google Inc. 3 * Copyright 2015 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 if (enum_name == "CONNECTION_BLUETOOTH") { 64 if (enum_name == "CONNECTION_BLUETOOTH") {
65 return NetworkType::NETWORK_BLUETOOTH; 65 return NetworkType::NETWORK_BLUETOOTH;
66 } 66 }
67 if (enum_name == "CONNECTION_NONE") { 67 if (enum_name == "CONNECTION_NONE") {
68 return NetworkType::NETWORK_NONE; 68 return NetworkType::NETWORK_NONE;
69 } 69 }
70 ASSERT(false); 70 ASSERT(false);
71 return NetworkType::NETWORK_UNKNOWN; 71 return NetworkType::NETWORK_UNKNOWN;
72 } 72 }
73 73
74 static rtc::AdapterType AdapterTypeFromNetworkType(NetworkType network_type) {
75 switch (network_type) {
76 case NETWORK_UNKNOWN:
77 RTC_DCHECK(false) << "Unknown network type ";
78 return rtc::ADAPTER_TYPE_UNKNOWN;
79 case NETWORK_ETHERNET:
80 return rtc::ADAPTER_TYPE_ETHERNET;
81 case NETWORK_WIFI:
82 return rtc::ADAPTER_TYPE_WIFI;
83 case NETWORK_4G:
84 case NETWORK_3G:
85 case NETWORK_2G:
86 return rtc::ADAPTER_TYPE_CELLULAR;
87 case NETWORK_BLUETOOTH:
88 // There is no corresponding mapping for bluetooth networks.
89 // Map it to VPN for now.
90 return rtc::ADAPTER_TYPE_VPN;
91 default:
92 RTC_DCHECK(false) << "Invalid network type " << network_type;
93 return rtc::ADAPTER_TYPE_UNKNOWN;
94 }
95 }
96
74 static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) { 97 static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) {
75 jclass j_ip_address_class = GetObjectClass(jni, j_ip_address); 98 jclass j_ip_address_class = GetObjectClass(jni, j_ip_address);
76 jfieldID j_address_id = GetFieldID(jni, j_ip_address_class, "address", "[B"); 99 jfieldID j_address_id = GetFieldID(jni, j_ip_address_class, "address", "[B");
77 jbyteArray j_addresses = 100 jbyteArray j_addresses =
78 static_cast<jbyteArray>(GetObjectField(jni, j_ip_address, j_address_id)); 101 static_cast<jbyteArray>(GetObjectField(jni, j_ip_address, j_address_id));
79 size_t address_length = jni->GetArrayLength(j_addresses); 102 size_t address_length = jni->GetArrayLength(j_addresses);
80 jbyte* addr_array = jni->GetByteArrayElements(j_addresses, nullptr); 103 jbyte* addr_array = jni->GetByteArrayElements(j_addresses, nullptr);
81 CHECK_EXCEPTION(jni) << "Error during GetIPAddressFromJava"; 104 CHECK_EXCEPTION(jni) << "Error during GetIPAddressFromJava";
82 if (address_length == 4) { 105 if (address_length == 4) {
83 // IP4 106 // IP4
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 started_ = true; 202 started_ = true;
180 203
181 // This is kind of magic behavior, but doing this allows the SocketServer to 204 // This is kind of magic behavior, but doing this allows the SocketServer to
182 // use this as a NetworkBinder to bind sockets on a particular network when 205 // use this as a NetworkBinder to bind sockets on a particular network when
183 // it creates sockets. 206 // it creates sockets.
184 worker_thread()->socketserver()->set_network_binder(this); 207 worker_thread()->socketserver()->set_network_binder(this);
185 208
186 jmethodID m = 209 jmethodID m =
187 GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V"); 210 GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V");
188 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); 211 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
189 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.startMonitoring"; 212 CHECK_EXCEPTION(jni()) << "Error during CallVoidMethod";
190 } 213 }
191 214
192 void AndroidNetworkMonitor::Stop() { 215 void AndroidNetworkMonitor::Stop() {
193 RTC_CHECK(thread_checker_.CalledOnValidThread()); 216 RTC_CHECK(thread_checker_.CalledOnValidThread());
194 if (!started_) { 217 if (!started_) {
195 return; 218 return;
196 } 219 }
197 started_ = false; 220 started_ = false;
198 221
199 // Once the network monitor stops, it will clear all network information and 222 // Once the network monitor stops, it will clear all network information and
200 // it won't find the network handle to bind anyway. 223 // it won't find the network handle to bind anyway.
201 if (worker_thread()->socketserver()->network_binder() == this) { 224 if (worker_thread()->socketserver()->network_binder() == this) {
202 worker_thread()->socketserver()->set_network_binder(nullptr); 225 worker_thread()->socketserver()->set_network_binder(nullptr);
203 } 226 }
204 227
205 jmethodID m = 228 jmethodID m =
206 GetMethodID(jni(), *j_network_monitor_class_, "stopMonitoring", "(J)V"); 229 GetMethodID(jni(), *j_network_monitor_class_, "stopMonitoring", "(J)V");
207 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this)); 230 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
208 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring"; 231 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring";
209 232
210 network_info_by_address_.clear(); 233 network_info_by_handle_.clear();
234 }
235
236 NetworkInformation* AndroidNetworkMonitor::GetNetworkInfoFromAddress(
237 const rtc::IPAddress& address) {
238 // 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.
239 // order. By searching in the reverse direction, the one that was created most
240 // recently is found first in the (unlikely) case that two handles have the
241 // same IP address (e.g., caused by accidentally not deleting the old handle).
242 auto& networks = network_info_by_handle_;
243 auto it = std::find_if(
244 networks.rbegin(), networks.rend(),
245 [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.
246 auto& addresses = pos.second.ip_addresses;
247 return std::find(addresses.begin(), addresses.end(), address) !=
248 addresses.end();
249 });
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
250 return (it != networks.rend()) ? &(it->second) : nullptr;
211 } 251 }
212 252
213 int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd, 253 int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd,
214 const rtc::IPAddress& address) { 254 const rtc::IPAddress& address) {
215 RTC_CHECK(thread_checker_.CalledOnValidThread()); 255 RTC_CHECK(thread_checker_.CalledOnValidThread());
216 auto it = network_info_by_address_.find(address); 256 // Android prior to Lollipop didn't have support for binding sockets to
217 if (it == network_info_by_address_.end()) { 257 // networks. However, in that case it should not have reached here because
258 // |network_info_by_handle_| should only be populated in Android Lollipop
259 // and above.
260 // TODO(honghaiz): Add a check for Android version here so that it won't try
261 // to look for handle if the Android version is before Lollipop.
262 NetworkInformation* network = GetNetworkInfoFromAddress(address);
263 if (network == nullptr) {
218 return rtc::NETWORK_BIND_ADDRESS_NOT_FOUND; 264 return rtc::NETWORK_BIND_ADDRESS_NOT_FOUND;
219 } 265 }
220 // Android prior to Lollipop didn't have support for binding sockets to
221 // networks. However, in that case it should not have reached here because
222 // |network_info_by_address_| should only be populated in Android Lollipop
223 // and above.
224 NetworkInformation network = it->second;
225 266
226 // NOTE: This does rely on Android implementation details, but 267 // NOTE: This does rely on Android implementation details, but
227 // these details are unlikely to change. 268 // these details are unlikely to change.
228 typedef int (*SetNetworkForSocket)(unsigned netId, int socketFd); 269 typedef int (*SetNetworkForSocket)(unsigned netId, int socketFd);
229 static SetNetworkForSocket setNetworkForSocket; 270 static SetNetworkForSocket setNetworkForSocket;
230 // This is not threadsafe, but we are running this only on the worker thread. 271 // This is not threadsafe, but we are running this only on the worker thread.
231 if (setNetworkForSocket == nullptr) { 272 if (setNetworkForSocket == nullptr) {
232 // Android's netd client library should always be loaded in our address 273 // Android's netd client library should always be loaded in our address
233 // space as it shims libc functions like connect(). 274 // space as it shims libc functions like connect().
234 const std::string net_library_path = "libnetd_client.so"; 275 const std::string net_library_path = "libnetd_client.so";
235 void* lib = dlopen(net_library_path.c_str(), RTLD_LAZY); 276 void* lib = dlopen(net_library_path.c_str(), RTLD_LAZY);
236 if (lib == nullptr) { 277 if (lib == nullptr) {
237 LOG(LS_ERROR) << "Library " << net_library_path << " not found!"; 278 LOG(LS_ERROR) << "Library " << net_library_path << " not found!";
238 return rtc::NETWORK_BIND_NOT_IMPLEMENTED; 279 return rtc::NETWORK_BIND_NOT_IMPLEMENTED;
239 } 280 }
240 setNetworkForSocket = reinterpret_cast<SetNetworkForSocket>( 281 setNetworkForSocket = reinterpret_cast<SetNetworkForSocket>(
241 dlsym(lib, "setNetworkForSocket")); 282 dlsym(lib, "setNetworkForSocket"));
242 } 283 }
243 if (setNetworkForSocket == nullptr) { 284 if (setNetworkForSocket == nullptr) {
244 LOG(LS_ERROR) << "Symbol setNetworkForSocket not found "; 285 LOG(LS_ERROR) << "Symbol setNetworkForSocket not found ";
245 return rtc::NETWORK_BIND_NOT_IMPLEMENTED; 286 return rtc::NETWORK_BIND_NOT_IMPLEMENTED;
246 } 287 }
247 int rv = setNetworkForSocket(network.handle, socket_fd); 288 int rv = setNetworkForSocket(network->handle, socket_fd);
248 // If |network| has since disconnected, |rv| will be ENONET. Surface this as 289 // If |network| has since disconnected, |rv| will be ENONET. Surface this as
249 // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back 290 // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
250 // the less descriptive ERR_FAILED. 291 // the less descriptive ERR_FAILED.
251 if (rv == 0) { 292 if (rv == 0) {
252 return rtc::NETWORK_BIND_SUCCESS; 293 return rtc::NETWORK_BIND_SUCCESS;
253 } 294 }
254 if (rv == ENONET) { 295 if (rv == ENONET) {
255 return rtc::NETWORK_BIND_NETWORK_CHANGED; 296 return rtc::NETWORK_BIND_NETWORK_CHANGED;
256 } 297 }
257 return rtc::NETWORK_BIND_FAILURE; 298 return rtc::NETWORK_BIND_FAILURE;
258 } 299 }
259 300
260 void AndroidNetworkMonitor::OnNetworkAvailable( 301 void AndroidNetworkMonitor::OnNetworkConnected(
261 const NetworkInformation& network_info) { 302 const NetworkInformation& network_info) {
303 LOG(LS_INFO) << "Network connected: " << network_info.ToString();
262 worker_thread()->Invoke<void>(rtc::Bind( 304 worker_thread()->Invoke<void>(rtc::Bind(
263 &AndroidNetworkMonitor::OnNetworkAvailable_w, this, network_info)); 305 &AndroidNetworkMonitor::OnNetworkConnected_w, this, network_info));
264 } 306 }
265 307
266 void AndroidNetworkMonitor::OnNetworkAvailable_w( 308 void AndroidNetworkMonitor::OnNetworkConnected_w(
267 const NetworkInformation& network_info) { 309 const NetworkInformation& network_info) {
268 LOG(LS_INFO) << "Network available: " << network_info.ToString(); 310 network_info_by_handle_[network_info.handle] = network_info;
269 for (rtc::IPAddress address : network_info.ip_addresses) { 311 adapter_type_by_name_[network_info.interface_name] =
270 network_info_by_address_[address] = network_info; 312 AdapterTypeFromNetworkType(network_info.type);
313 }
314
315 void AndroidNetworkMonitor::OnNetworkDisconnected(NetworkHandle handle) {
316 LOG(LS_INFO) << "Network disconnected for handle " << handle;
317 worker_thread()->Invoke<void>(
318 rtc::Bind(&AndroidNetworkMonitor::OnNetworkDisconnected_w, this, handle));
319 }
320
321 void AndroidNetworkMonitor::OnNetworkDisconnected_w(NetworkHandle handle) {
322 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.
323 }
324
325 void AndroidNetworkMonitor::SetNetworkInfos(
326 const std::vector<NetworkInformation>& network_infos) {
327 RTC_CHECK(thread_checker_.CalledOnValidThread());
328 network_info_by_handle_.clear();
329 for (NetworkInformation network : network_infos) {
330 OnNetworkConnected_w(network);
271 } 331 }
272 } 332 }
273 333
334 rtc::AdapterType AndroidNetworkMonitor::GetAdapterType(
335 const std::string& if_name) {
336 // If not found, the default type is 0 (ADAPTER_TYPE_UNKNOWN).
337 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.
338 }
339
274 rtc::NetworkMonitorInterface* 340 rtc::NetworkMonitorInterface*
275 AndroidNetworkMonitorFactory::CreateNetworkMonitor() { 341 AndroidNetworkMonitorFactory::CreateNetworkMonitor() {
276 return new AndroidNetworkMonitor(); 342 return new AndroidNetworkMonitor();
277 } 343 }
278 344
279 JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)( 345 JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)(
280 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor) { 346 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor) {
281 rtc::NetworkMonitorInterface* network_monitor = 347 rtc::NetworkMonitorInterface* network_monitor =
282 reinterpret_cast<rtc::NetworkMonitorInterface*>(j_native_monitor); 348 reinterpret_cast<rtc::NetworkMonitorInterface*>(j_native_monitor);
283 network_monitor->OnNetworksChanged(); 349 network_monitor->OnNetworksChanged();
284 } 350 }
285 351
352 JOW(void, NetworkMonitor_nativeNotifyOfActiveNetworkList)(
353 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
354 jobjectArray j_network_infos) {
355 AndroidNetworkMonitor* network_monitor =
356 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
357 std::vector<NetworkInformation> network_infos;
358 size_t num_networks = jni->GetArrayLength(j_network_infos);
359 for (size_t i = 0; i < num_networks; ++i) {
360 jobject j_network_info = jni->GetObjectArrayElement(j_network_infos, i);
361 CHECK_EXCEPTION(jni) << "Error during GetObjectArrayElement";
362 network_infos.push_back(GetNetworkInformationFromJava(jni, j_network_info));
363 }
364 network_monitor->SetNetworkInfos(network_infos);
365 }
366
286 JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)( 367 JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)(
287 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor, 368 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
288 jobject j_network_info) { 369 jobject j_network_info) {
289 AndroidNetworkMonitor* network_monitor = 370 AndroidNetworkMonitor* network_monitor =
290 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor); 371 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
291 NetworkInformation network_info = 372 NetworkInformation network_info =
292 GetNetworkInformationFromJava(jni, j_network_info); 373 GetNetworkInformationFromJava(jni, j_network_info);
293 network_monitor->OnNetworkAvailable(network_info); 374 network_monitor->OnNetworkConnected(network_info);
375 }
376
377 JOW(void, NetworkMonitor_nativeNotifyOfNetworkDisconnect)(
378 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
379 jint network_handle) {
380 AndroidNetworkMonitor* network_monitor =
381 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
382 network_monitor->OnNetworkDisconnected(
383 static_cast<NetworkHandle>(network_handle));
294 } 384 }
295 385
296 } // namespace webrtc_jni 386 } // namespace webrtc_jni
OLDNEW
« no previous file with comments | « talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h ('k') | webrtc/base/network.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698