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

Side by Side Diff: webrtc/api/android/jni/androidnetworkmonitor_jni.cc

Issue 2106333005: Revert of Combine webrtc/api/java/android and webrtc/api/java/src. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 5 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
OLDNEW
(Empty)
1 /*
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/api/android/jni/androidnetworkmonitor_jni.h"
12
13 #include <dlfcn.h>
14
15 #include "webrtc/api/android/jni/classreferenceholder.h"
16 #include "webrtc/api/android/jni/jni_helpers.h"
17 #include "webrtc/base/bind.h"
18 #include "webrtc/base/common.h"
19 #include "webrtc/base/ipaddress.h"
20
21 namespace webrtc_jni {
22
23 jobject AndroidNetworkMonitor::application_context_ = nullptr;
24
25 static NetworkType GetNetworkTypeFromJava(JNIEnv* jni, jobject j_network_type) {
26 std::string enum_name =
27 GetJavaEnumName(jni, "org/webrtc/NetworkMonitorAutoDetect$ConnectionType",
28 j_network_type);
29 if (enum_name == "CONNECTION_UNKNOWN") {
30 return NetworkType::NETWORK_UNKNOWN;
31 }
32 if (enum_name == "CONNECTION_ETHERNET") {
33 return NetworkType::NETWORK_ETHERNET;
34 }
35 if (enum_name == "CONNECTION_WIFI") {
36 return NetworkType::NETWORK_WIFI;
37 }
38 if (enum_name == "CONNECTION_4G") {
39 return NetworkType::NETWORK_4G;
40 }
41 if (enum_name == "CONNECTION_3G") {
42 return NetworkType::NETWORK_3G;
43 }
44 if (enum_name == "CONNECTION_2G") {
45 return NetworkType::NETWORK_2G;
46 }
47 if (enum_name == "CONNECTION_UNKNOWN_CELLULAR") {
48 return NetworkType::NETWORK_UNKNOWN_CELLULAR;
49 }
50 if (enum_name == "CONNECTION_BLUETOOTH") {
51 return NetworkType::NETWORK_BLUETOOTH;
52 }
53 if (enum_name == "CONNECTION_NONE") {
54 return NetworkType::NETWORK_NONE;
55 }
56 ASSERT(false);
57 return NetworkType::NETWORK_UNKNOWN;
58 }
59
60 static rtc::AdapterType AdapterTypeFromNetworkType(NetworkType network_type) {
61 switch (network_type) {
62 case NETWORK_UNKNOWN:
63 return rtc::ADAPTER_TYPE_UNKNOWN;
64 case NETWORK_ETHERNET:
65 return rtc::ADAPTER_TYPE_ETHERNET;
66 case NETWORK_WIFI:
67 return rtc::ADAPTER_TYPE_WIFI;
68 case NETWORK_4G:
69 case NETWORK_3G:
70 case NETWORK_2G:
71 case NETWORK_UNKNOWN_CELLULAR:
72 return rtc::ADAPTER_TYPE_CELLULAR;
73 case NETWORK_BLUETOOTH:
74 // There is no corresponding mapping for bluetooth networks.
75 // Map it to VPN for now.
76 return rtc::ADAPTER_TYPE_VPN;
77 default:
78 RTC_DCHECK(false) << "Invalid network type " << network_type;
79 return rtc::ADAPTER_TYPE_UNKNOWN;
80 }
81 }
82
83 static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) {
84 jclass j_ip_address_class = GetObjectClass(jni, j_ip_address);
85 jfieldID j_address_id = GetFieldID(jni, j_ip_address_class, "address", "[B");
86 jbyteArray j_addresses =
87 static_cast<jbyteArray>(GetObjectField(jni, j_ip_address, j_address_id));
88 size_t address_length = jni->GetArrayLength(j_addresses);
89 jbyte* addr_array = jni->GetByteArrayElements(j_addresses, nullptr);
90 CHECK_EXCEPTION(jni) << "Error during GetIPAddressFromJava";
91 if (address_length == 4) {
92 // IP4
93 struct in_addr ip4_addr;
94 memcpy(&ip4_addr.s_addr, addr_array, 4);
95 jni->ReleaseByteArrayElements(j_addresses, addr_array, JNI_ABORT);
96 return rtc::IPAddress(ip4_addr);
97 }
98 // IP6
99 RTC_CHECK(address_length == 16);
100 struct in6_addr ip6_addr;
101 memcpy(ip6_addr.s6_addr, addr_array, address_length);
102 jni->ReleaseByteArrayElements(j_addresses, addr_array, JNI_ABORT);
103 return rtc::IPAddress(ip6_addr);
104 }
105
106 static void GetIPAddressesFromJava(JNIEnv* jni,
107 jobjectArray j_ip_addresses,
108 std::vector<rtc::IPAddress>* ip_addresses) {
109 ip_addresses->clear();
110 size_t num_addresses = jni->GetArrayLength(j_ip_addresses);
111 CHECK_EXCEPTION(jni) << "Error during GetArrayLength";
112 for (size_t i = 0; i < num_addresses; ++i) {
113 jobject j_ip_address = jni->GetObjectArrayElement(j_ip_addresses, i);
114 CHECK_EXCEPTION(jni) << "Error during GetObjectArrayElement";
115 rtc::IPAddress ip = GetIPAddressFromJava(jni, j_ip_address);
116 ip_addresses->push_back(ip);
117 }
118 }
119
120 static NetworkInformation GetNetworkInformationFromJava(
121 JNIEnv* jni,
122 jobject j_network_info) {
123 jclass j_network_info_class = GetObjectClass(jni, j_network_info);
124 jfieldID j_interface_name_id =
125 GetFieldID(jni, j_network_info_class, "name", "Ljava/lang/String;");
126 jfieldID j_handle_id = GetFieldID(jni, j_network_info_class, "handle", "I");
127 jfieldID j_type_id =
128 GetFieldID(jni, j_network_info_class, "type",
129 "Lorg/webrtc/NetworkMonitorAutoDetect$ConnectionType;");
130 jfieldID j_ip_addresses_id =
131 GetFieldID(jni, j_network_info_class, "ipAddresses",
132 "[Lorg/webrtc/NetworkMonitorAutoDetect$IPAddress;");
133
134 NetworkInformation network_info;
135 network_info.interface_name = JavaToStdString(
136 jni, GetStringField(jni, j_network_info, j_interface_name_id));
137 network_info.handle =
138 static_cast<NetworkHandle>(GetIntField(jni, j_network_info, j_handle_id));
139 network_info.type = GetNetworkTypeFromJava(
140 jni, GetObjectField(jni, j_network_info, j_type_id));
141 jobjectArray j_ip_addresses = static_cast<jobjectArray>(
142 GetObjectField(jni, j_network_info, j_ip_addresses_id));
143 GetIPAddressesFromJava(jni, j_ip_addresses, &network_info.ip_addresses);
144 return network_info;
145 }
146
147 std::string NetworkInformation::ToString() const {
148 std::stringstream ss;
149 ss << "NetInfo[name " << interface_name << "; handle " << handle << "; type "
150 << type << "; address";
151 for (const rtc::IPAddress address : ip_addresses) {
152 ss << " " << address.ToString();
153 }
154 ss << "]";
155 return ss.str();
156 }
157
158 // static
159 void AndroidNetworkMonitor::SetAndroidContext(JNIEnv* jni, jobject context) {
160 if (application_context_) {
161 jni->DeleteGlobalRef(application_context_);
162 }
163 application_context_ = NewGlobalRef(jni, context);
164 }
165
166 AndroidNetworkMonitor::AndroidNetworkMonitor()
167 : j_network_monitor_class_(jni(),
168 FindClass(jni(), "org/webrtc/NetworkMonitor")),
169 j_network_monitor_(
170 jni(),
171 jni()->CallStaticObjectMethod(
172 *j_network_monitor_class_,
173 GetStaticMethodID(
174 jni(),
175 *j_network_monitor_class_,
176 "init",
177 "(Landroid/content/Context;)Lorg/webrtc/NetworkMonitor;"),
178 application_context_)) {
179 ASSERT(application_context_ != nullptr);
180 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.init";
181 }
182
183 void AndroidNetworkMonitor::Start() {
184 RTC_CHECK(thread_checker_.CalledOnValidThread());
185 if (started_) {
186 return;
187 }
188 started_ = true;
189
190 // This is kind of magic behavior, but doing this allows the SocketServer to
191 // use this as a NetworkBinder to bind sockets on a particular network when
192 // it creates sockets.
193 worker_thread()->socketserver()->set_network_binder(this);
194
195 jmethodID m =
196 GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V");
197 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
198 CHECK_EXCEPTION(jni()) << "Error during CallVoidMethod";
199 }
200
201 void AndroidNetworkMonitor::Stop() {
202 RTC_CHECK(thread_checker_.CalledOnValidThread());
203 if (!started_) {
204 return;
205 }
206 started_ = false;
207
208 // Once the network monitor stops, it will clear all network information and
209 // it won't find the network handle to bind anyway.
210 if (worker_thread()->socketserver()->network_binder() == this) {
211 worker_thread()->socketserver()->set_network_binder(nullptr);
212 }
213
214 jmethodID m =
215 GetMethodID(jni(), *j_network_monitor_class_, "stopMonitoring", "(J)V");
216 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
217 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring";
218
219 network_handle_by_address_.clear();
220 network_info_by_handle_.clear();
221 }
222
223 int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd,
224 const rtc::IPAddress& address) {
225 RTC_CHECK(thread_checker_.CalledOnValidThread());
226 // Android prior to Lollipop didn't have support for binding sockets to
227 // networks. However, in that case it should not have reached here because
228 // |network_handle_by_address_| should only be populated in Android Lollipop
229 // and above.
230 // TODO(honghaiz): Add a check for Android version here so that it won't try
231 // to look for handle if the Android version is before Lollipop.
232 auto iter = network_handle_by_address_.find(address);
233 if (iter == network_handle_by_address_.end()) {
234 return rtc::NETWORK_BIND_ADDRESS_NOT_FOUND;
235 }
236 NetworkHandle network_handle = iter->second;
237
238 // NOTE: This does rely on Android implementation details, but
239 // these details are unlikely to change.
240 typedef int (*SetNetworkForSocket)(unsigned netId, int socketFd);
241 static SetNetworkForSocket setNetworkForSocket;
242 // This is not threadsafe, but we are running this only on the worker thread.
243 if (setNetworkForSocket == nullptr) {
244 // Android's netd client library should always be loaded in our address
245 // space as it shims libc functions like connect().
246 const std::string net_library_path = "libnetd_client.so";
247 void* lib = dlopen(net_library_path.c_str(), RTLD_LAZY);
248 if (lib == nullptr) {
249 LOG(LS_ERROR) << "Library " << net_library_path << " not found!";
250 return rtc::NETWORK_BIND_NOT_IMPLEMENTED;
251 }
252 setNetworkForSocket = reinterpret_cast<SetNetworkForSocket>(
253 dlsym(lib, "setNetworkForSocket"));
254 }
255 if (setNetworkForSocket == nullptr) {
256 LOG(LS_ERROR) << "Symbol setNetworkForSocket not found ";
257 return rtc::NETWORK_BIND_NOT_IMPLEMENTED;
258 }
259 int rv = setNetworkForSocket(network_handle, socket_fd);
260 // If |network| has since disconnected, |rv| will be ENONET. Surface this as
261 // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
262 // the less descriptive ERR_FAILED.
263 if (rv == 0) {
264 return rtc::NETWORK_BIND_SUCCESS;
265 }
266 if (rv == ENONET) {
267 return rtc::NETWORK_BIND_NETWORK_CHANGED;
268 }
269 return rtc::NETWORK_BIND_FAILURE;
270 }
271
272 void AndroidNetworkMonitor::OnNetworkConnected(
273 const NetworkInformation& network_info) {
274 worker_thread()->Invoke<void>(
275 RTC_FROM_HERE, rtc::Bind(&AndroidNetworkMonitor::OnNetworkConnected_w,
276 this, network_info));
277 // Fire SignalNetworksChanged to update the list of networks.
278 OnNetworksChanged();
279 }
280
281 void AndroidNetworkMonitor::OnNetworkConnected_w(
282 const NetworkInformation& network_info) {
283 LOG(LS_INFO) << "Network connected: " << network_info.ToString();
284 adapter_type_by_name_[network_info.interface_name] =
285 AdapterTypeFromNetworkType(network_info.type);
286 network_info_by_handle_[network_info.handle] = network_info;
287 for (const rtc::IPAddress& address : network_info.ip_addresses) {
288 network_handle_by_address_[address] = network_info.handle;
289 }
290 }
291
292 void AndroidNetworkMonitor::OnNetworkDisconnected(NetworkHandle handle) {
293 LOG(LS_INFO) << "Network disconnected for handle " << handle;
294 worker_thread()->Invoke<void>(
295 RTC_FROM_HERE,
296 rtc::Bind(&AndroidNetworkMonitor::OnNetworkDisconnected_w, this, handle));
297 }
298
299 void AndroidNetworkMonitor::OnNetworkDisconnected_w(NetworkHandle handle) {
300 auto iter = network_info_by_handle_.find(handle);
301 if (iter != network_info_by_handle_.end()) {
302 for (const rtc::IPAddress& address : iter->second.ip_addresses) {
303 network_handle_by_address_.erase(address);
304 }
305 network_info_by_handle_.erase(iter);
306 }
307 }
308
309 void AndroidNetworkMonitor::SetNetworkInfos(
310 const std::vector<NetworkInformation>& network_infos) {
311 RTC_CHECK(thread_checker_.CalledOnValidThread());
312 network_handle_by_address_.clear();
313 network_info_by_handle_.clear();
314 LOG(LS_INFO) << "Android network monitor found " << network_infos.size()
315 << " networks";
316 for (NetworkInformation network : network_infos) {
317 OnNetworkConnected_w(network);
318 }
319 }
320
321 rtc::AdapterType AndroidNetworkMonitor::GetAdapterType(
322 const std::string& if_name) {
323 auto iter = adapter_type_by_name_.find(if_name);
324 rtc::AdapterType type = (iter == adapter_type_by_name_.end())
325 ? rtc::ADAPTER_TYPE_UNKNOWN
326 : iter->second;
327 if (type == rtc::ADAPTER_TYPE_UNKNOWN) {
328 LOG(LS_WARNING) << "Get an unknown type for the interface " << if_name;
329 }
330 return type;
331 }
332
333 rtc::NetworkMonitorInterface*
334 AndroidNetworkMonitorFactory::CreateNetworkMonitor() {
335 return new AndroidNetworkMonitor();
336 }
337
338 JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)(
339 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor) {
340 rtc::NetworkMonitorInterface* network_monitor =
341 reinterpret_cast<rtc::NetworkMonitorInterface*>(j_native_monitor);
342 network_monitor->OnNetworksChanged();
343 }
344
345 JOW(void, NetworkMonitor_nativeNotifyOfActiveNetworkList)(
346 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
347 jobjectArray j_network_infos) {
348 AndroidNetworkMonitor* network_monitor =
349 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
350 std::vector<NetworkInformation> network_infos;
351 size_t num_networks = jni->GetArrayLength(j_network_infos);
352 for (size_t i = 0; i < num_networks; ++i) {
353 jobject j_network_info = jni->GetObjectArrayElement(j_network_infos, i);
354 CHECK_EXCEPTION(jni) << "Error during GetObjectArrayElement";
355 network_infos.push_back(GetNetworkInformationFromJava(jni, j_network_info));
356 }
357 network_monitor->SetNetworkInfos(network_infos);
358 }
359
360 JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)(
361 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
362 jobject j_network_info) {
363 AndroidNetworkMonitor* network_monitor =
364 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
365 NetworkInformation network_info =
366 GetNetworkInformationFromJava(jni, j_network_info);
367 network_monitor->OnNetworkConnected(network_info);
368 }
369
370 JOW(void, NetworkMonitor_nativeNotifyOfNetworkDisconnect)(
371 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
372 jint network_handle) {
373 AndroidNetworkMonitor* network_monitor =
374 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
375 network_monitor->OnNetworkDisconnected(
376 static_cast<NetworkHandle>(network_handle));
377 }
378
379 } // namespace webrtc_jni
OLDNEW
« no previous file with comments | « webrtc/api/android/jni/androidnetworkmonitor_jni.h ('k') | webrtc/api/android/jni/androidvideocapturer_jni.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698