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

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

Issue 1610243002: Move talk/app/webrtc to webrtc/api (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Removed processing of api.gyp for Chromium builds 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
OLDNEW
(Empty)
1 /*
2 * libjingle
3 * Copyright 2015 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h"
29
30 #include <dlfcn.h>
31
32 #include "talk/app/webrtc/java/jni/classreferenceholder.h"
33 #include "talk/app/webrtc/java/jni/jni_helpers.h"
34 #include "webrtc/base/bind.h"
35 #include "webrtc/base/common.h"
36 #include "webrtc/base/ipaddress.h"
37
38 namespace webrtc_jni {
39
40 jobject AndroidNetworkMonitor::application_context_ = nullptr;
41
42 static NetworkType GetNetworkTypeFromJava(JNIEnv* jni, jobject j_network_type) {
43 std::string enum_name =
44 GetJavaEnumName(jni, "org/webrtc/NetworkMonitorAutoDetect$ConnectionType",
45 j_network_type);
46 if (enum_name == "CONNECTION_UNKNOWN") {
47 return NetworkType::NETWORK_UNKNOWN;
48 }
49 if (enum_name == "CONNECTION_ETHERNET") {
50 return NetworkType::NETWORK_ETHERNET;
51 }
52 if (enum_name == "CONNECTION_WIFI") {
53 return NetworkType::NETWORK_WIFI;
54 }
55 if (enum_name == "CONNECTION_4G") {
56 return NetworkType::NETWORK_4G;
57 }
58 if (enum_name == "CONNECTION_3G") {
59 return NetworkType::NETWORK_3G;
60 }
61 if (enum_name == "CONNECTION_2G") {
62 return NetworkType::NETWORK_2G;
63 }
64 if (enum_name == "CONNECTION_BLUETOOTH") {
65 return NetworkType::NETWORK_BLUETOOTH;
66 }
67 if (enum_name == "CONNECTION_NONE") {
68 return NetworkType::NETWORK_NONE;
69 }
70 ASSERT(false);
71 return NetworkType::NETWORK_UNKNOWN;
72 }
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
97 static rtc::IPAddress GetIPAddressFromJava(JNIEnv* jni, jobject j_ip_address) {
98 jclass j_ip_address_class = GetObjectClass(jni, j_ip_address);
99 jfieldID j_address_id = GetFieldID(jni, j_ip_address_class, "address", "[B");
100 jbyteArray j_addresses =
101 static_cast<jbyteArray>(GetObjectField(jni, j_ip_address, j_address_id));
102 size_t address_length = jni->GetArrayLength(j_addresses);
103 jbyte* addr_array = jni->GetByteArrayElements(j_addresses, nullptr);
104 CHECK_EXCEPTION(jni) << "Error during GetIPAddressFromJava";
105 if (address_length == 4) {
106 // IP4
107 struct in_addr ip4_addr;
108 memcpy(&ip4_addr.s_addr, addr_array, 4);
109 jni->ReleaseByteArrayElements(j_addresses, addr_array, JNI_ABORT);
110 return rtc::IPAddress(ip4_addr);
111 }
112 // IP6
113 RTC_CHECK(address_length == 16);
114 struct in6_addr ip6_addr;
115 memcpy(ip6_addr.s6_addr, addr_array, address_length);
116 jni->ReleaseByteArrayElements(j_addresses, addr_array, JNI_ABORT);
117 return rtc::IPAddress(ip6_addr);
118 }
119
120 static void GetIPAddressesFromJava(JNIEnv* jni,
121 jobjectArray j_ip_addresses,
122 std::vector<rtc::IPAddress>* ip_addresses) {
123 ip_addresses->clear();
124 size_t num_addresses = jni->GetArrayLength(j_ip_addresses);
125 CHECK_EXCEPTION(jni) << "Error during GetArrayLength";
126 for (size_t i = 0; i < num_addresses; ++i) {
127 jobject j_ip_address = jni->GetObjectArrayElement(j_ip_addresses, i);
128 CHECK_EXCEPTION(jni) << "Error during GetObjectArrayElement";
129 rtc::IPAddress ip = GetIPAddressFromJava(jni, j_ip_address);
130 ip_addresses->push_back(ip);
131 }
132 }
133
134 static NetworkInformation GetNetworkInformationFromJava(
135 JNIEnv* jni,
136 jobject j_network_info) {
137 jclass j_network_info_class = GetObjectClass(jni, j_network_info);
138 jfieldID j_interface_name_id =
139 GetFieldID(jni, j_network_info_class, "name", "Ljava/lang/String;");
140 jfieldID j_handle_id = GetFieldID(jni, j_network_info_class, "handle", "I");
141 jfieldID j_type_id =
142 GetFieldID(jni, j_network_info_class, "type",
143 "Lorg/webrtc/NetworkMonitorAutoDetect$ConnectionType;");
144 jfieldID j_ip_addresses_id =
145 GetFieldID(jni, j_network_info_class, "ipAddresses",
146 "[Lorg/webrtc/NetworkMonitorAutoDetect$IPAddress;");
147
148 NetworkInformation network_info;
149 network_info.interface_name = JavaToStdString(
150 jni, GetStringField(jni, j_network_info, j_interface_name_id));
151 network_info.handle =
152 static_cast<NetworkHandle>(GetIntField(jni, j_network_info, j_handle_id));
153 network_info.type = GetNetworkTypeFromJava(
154 jni, GetObjectField(jni, j_network_info, j_type_id));
155 jobjectArray j_ip_addresses = static_cast<jobjectArray>(
156 GetObjectField(jni, j_network_info, j_ip_addresses_id));
157 GetIPAddressesFromJava(jni, j_ip_addresses, &network_info.ip_addresses);
158 return network_info;
159 }
160
161 std::string NetworkInformation::ToString() const {
162 std::stringstream ss;
163 ss << "NetInfo[name " << interface_name << "; handle " << handle << "; type "
164 << type << "; address";
165 for (const rtc::IPAddress address : ip_addresses) {
166 ss << " " << address.ToString();
167 }
168 ss << "]";
169 return ss.str();
170 }
171
172 // static
173 void AndroidNetworkMonitor::SetAndroidContext(JNIEnv* jni, jobject context) {
174 if (application_context_) {
175 jni->DeleteGlobalRef(application_context_);
176 }
177 application_context_ = NewGlobalRef(jni, context);
178 }
179
180 AndroidNetworkMonitor::AndroidNetworkMonitor()
181 : j_network_monitor_class_(jni(),
182 FindClass(jni(), "org/webrtc/NetworkMonitor")),
183 j_network_monitor_(
184 jni(),
185 jni()->CallStaticObjectMethod(
186 *j_network_monitor_class_,
187 GetStaticMethodID(
188 jni(),
189 *j_network_monitor_class_,
190 "init",
191 "(Landroid/content/Context;)Lorg/webrtc/NetworkMonitor;"),
192 application_context_)) {
193 ASSERT(application_context_ != nullptr);
194 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.init";
195 }
196
197 void AndroidNetworkMonitor::Start() {
198 RTC_CHECK(thread_checker_.CalledOnValidThread());
199 if (started_) {
200 return;
201 }
202 started_ = true;
203
204 // This is kind of magic behavior, but doing this allows the SocketServer to
205 // use this as a NetworkBinder to bind sockets on a particular network when
206 // it creates sockets.
207 worker_thread()->socketserver()->set_network_binder(this);
208
209 jmethodID m =
210 GetMethodID(jni(), *j_network_monitor_class_, "startMonitoring", "(J)V");
211 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
212 CHECK_EXCEPTION(jni()) << "Error during CallVoidMethod";
213 }
214
215 void AndroidNetworkMonitor::Stop() {
216 RTC_CHECK(thread_checker_.CalledOnValidThread());
217 if (!started_) {
218 return;
219 }
220 started_ = false;
221
222 // Once the network monitor stops, it will clear all network information and
223 // it won't find the network handle to bind anyway.
224 if (worker_thread()->socketserver()->network_binder() == this) {
225 worker_thread()->socketserver()->set_network_binder(nullptr);
226 }
227
228 jmethodID m =
229 GetMethodID(jni(), *j_network_monitor_class_, "stopMonitoring", "(J)V");
230 jni()->CallVoidMethod(*j_network_monitor_, m, jlongFromPointer(this));
231 CHECK_EXCEPTION(jni()) << "Error during NetworkMonitor.stopMonitoring";
232
233 network_handle_by_address_.clear();
234 network_info_by_handle_.clear();
235 }
236
237 int AndroidNetworkMonitor::BindSocketToNetwork(int socket_fd,
238 const rtc::IPAddress& address) {
239 RTC_CHECK(thread_checker_.CalledOnValidThread());
240 // Android prior to Lollipop didn't have support for binding sockets to
241 // networks. However, in that case it should not have reached here because
242 // |network_handle_by_address_| should only be populated in Android Lollipop
243 // and above.
244 // TODO(honghaiz): Add a check for Android version here so that it won't try
245 // to look for handle if the Android version is before Lollipop.
246 auto iter = network_handle_by_address_.find(address);
247 if (iter == network_handle_by_address_.end()) {
248 return rtc::NETWORK_BIND_ADDRESS_NOT_FOUND;
249 }
250 NetworkHandle network_handle = iter->second;
251
252 // NOTE: This does rely on Android implementation details, but
253 // these details are unlikely to change.
254 typedef int (*SetNetworkForSocket)(unsigned netId, int socketFd);
255 static SetNetworkForSocket setNetworkForSocket;
256 // This is not threadsafe, but we are running this only on the worker thread.
257 if (setNetworkForSocket == nullptr) {
258 // Android's netd client library should always be loaded in our address
259 // space as it shims libc functions like connect().
260 const std::string net_library_path = "libnetd_client.so";
261 void* lib = dlopen(net_library_path.c_str(), RTLD_LAZY);
262 if (lib == nullptr) {
263 LOG(LS_ERROR) << "Library " << net_library_path << " not found!";
264 return rtc::NETWORK_BIND_NOT_IMPLEMENTED;
265 }
266 setNetworkForSocket = reinterpret_cast<SetNetworkForSocket>(
267 dlsym(lib, "setNetworkForSocket"));
268 }
269 if (setNetworkForSocket == nullptr) {
270 LOG(LS_ERROR) << "Symbol setNetworkForSocket not found ";
271 return rtc::NETWORK_BIND_NOT_IMPLEMENTED;
272 }
273 int rv = setNetworkForSocket(network_handle, socket_fd);
274 // If |network| has since disconnected, |rv| will be ENONET. Surface this as
275 // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
276 // the less descriptive ERR_FAILED.
277 if (rv == 0) {
278 return rtc::NETWORK_BIND_SUCCESS;
279 }
280 if (rv == ENONET) {
281 return rtc::NETWORK_BIND_NETWORK_CHANGED;
282 }
283 return rtc::NETWORK_BIND_FAILURE;
284 }
285
286 void AndroidNetworkMonitor::OnNetworkConnected(
287 const NetworkInformation& network_info) {
288 LOG(LS_INFO) << "Network connected: " << network_info.ToString();
289 worker_thread()->Invoke<void>(rtc::Bind(
290 &AndroidNetworkMonitor::OnNetworkConnected_w, this, network_info));
291 }
292
293 void AndroidNetworkMonitor::OnNetworkConnected_w(
294 const NetworkInformation& network_info) {
295 adapter_type_by_name_[network_info.interface_name] =
296 AdapterTypeFromNetworkType(network_info.type);
297 network_info_by_handle_[network_info.handle] = network_info;
298 for (const rtc::IPAddress& address : network_info.ip_addresses) {
299 network_handle_by_address_[address] = network_info.handle;
300 }
301 }
302
303 void AndroidNetworkMonitor::OnNetworkDisconnected(NetworkHandle handle) {
304 LOG(LS_INFO) << "Network disconnected for handle " << handle;
305 worker_thread()->Invoke<void>(
306 rtc::Bind(&AndroidNetworkMonitor::OnNetworkDisconnected_w, this, handle));
307 }
308
309 void AndroidNetworkMonitor::OnNetworkDisconnected_w(NetworkHandle handle) {
310 auto iter = network_info_by_handle_.find(handle);
311 if (iter != network_info_by_handle_.end()) {
312 for (const rtc::IPAddress& address : iter->second.ip_addresses) {
313 network_handle_by_address_.erase(address);
314 }
315 network_info_by_handle_.erase(iter);
316 }
317 }
318
319 void AndroidNetworkMonitor::SetNetworkInfos(
320 const std::vector<NetworkInformation>& network_infos) {
321 RTC_CHECK(thread_checker_.CalledOnValidThread());
322 network_handle_by_address_.clear();
323 network_info_by_handle_.clear();
324 for (NetworkInformation network : network_infos) {
325 OnNetworkConnected_w(network);
326 }
327 }
328
329 rtc::AdapterType AndroidNetworkMonitor::GetAdapterType(
330 const std::string& if_name) {
331 auto iter = adapter_type_by_name_.find(if_name);
332 if (iter == adapter_type_by_name_.end()) {
333 return rtc::ADAPTER_TYPE_UNKNOWN;
334 }
335 return iter->second;
336 }
337
338 rtc::NetworkMonitorInterface*
339 AndroidNetworkMonitorFactory::CreateNetworkMonitor() {
340 return new AndroidNetworkMonitor();
341 }
342
343 JOW(void, NetworkMonitor_nativeNotifyConnectionTypeChanged)(
344 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor) {
345 rtc::NetworkMonitorInterface* network_monitor =
346 reinterpret_cast<rtc::NetworkMonitorInterface*>(j_native_monitor);
347 network_monitor->OnNetworksChanged();
348 }
349
350 JOW(void, NetworkMonitor_nativeNotifyOfActiveNetworkList)(
351 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
352 jobjectArray j_network_infos) {
353 AndroidNetworkMonitor* network_monitor =
354 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
355 std::vector<NetworkInformation> network_infos;
356 size_t num_networks = jni->GetArrayLength(j_network_infos);
357 for (size_t i = 0; i < num_networks; ++i) {
358 jobject j_network_info = jni->GetObjectArrayElement(j_network_infos, i);
359 CHECK_EXCEPTION(jni) << "Error during GetObjectArrayElement";
360 network_infos.push_back(GetNetworkInformationFromJava(jni, j_network_info));
361 }
362 network_monitor->SetNetworkInfos(network_infos);
363 }
364
365 JOW(void, NetworkMonitor_nativeNotifyOfNetworkConnect)(
366 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
367 jobject j_network_info) {
368 AndroidNetworkMonitor* network_monitor =
369 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
370 NetworkInformation network_info =
371 GetNetworkInformationFromJava(jni, j_network_info);
372 network_monitor->OnNetworkConnected(network_info);
373 }
374
375 JOW(void, NetworkMonitor_nativeNotifyOfNetworkDisconnect)(
376 JNIEnv* jni, jobject j_monitor, jlong j_native_monitor,
377 jint network_handle) {
378 AndroidNetworkMonitor* network_monitor =
379 reinterpret_cast<AndroidNetworkMonitor*>(j_native_monitor);
380 network_monitor->OnNetworkDisconnected(
381 static_cast<NetworkHandle>(network_handle));
382 }
383
384 } // namespace webrtc_jni
OLDNEW
« no previous file with comments | « talk/app/webrtc/java/jni/androidnetworkmonitor_jni.h ('k') | talk/app/webrtc/java/jni/androidvideocapturer_jni.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698