1 /*
2 * Copyright 2008, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "wifi"
18
19 #include "jni.h"
20 #include "JniConstants.h"
21 #include <ScopedUtfChars.h>
22 #include <ScopedBytes.h>
23 #include <utils/misc.h>
24 #include <utils/Log.h>
25 #include <utils/String16.h>
26 #include <ctype.h>
27 #include <stdlib.h>
28 #include <sys/socket.h>
29 #include <sys/klog.h>
30 #include <linux/if.h>
31 #include <linux/if_arp.h>
32
33 #include <algorithm>
34 #include <limits>
35 #include <vector>
36
37 #include "wifi.h"
38 #include "wifi_hal.h"
39 #include "jni_helper.h"
40 #include "rtt.h"
41 #include "wifi_hal_stub.h"
42 #define REPLY_BUF_SIZE 4096 + 1 // wpa_supplicant's maximum size + 1 for nul
43 #define EVENT_BUF_SIZE 2048
44 #define WAKE_REASON_TYPE_MAX 10
45
46 namespace android {
47
48 extern "C"
49 jint Java_com_android_server_wifi_WifiNative_registerNanNatives(JNIEnv* env, jclass clazz);
50
51 static jint DBG = false;
52
53 //Please put all HAL function call here and call from the function table instead of directly call
54 wifi_hal_fn hal_fn;
doCommand(JNIEnv * env,jstring javaCommand,char * reply,size_t reply_len)55 static bool doCommand(JNIEnv* env, jstring javaCommand,
56 char* reply, size_t reply_len) {
57 ScopedUtfChars command(env, javaCommand);
58 if (command.c_str() == NULL) {
59 return false; // ScopedUtfChars already threw on error.
60 }
61
62 if (DBG) {
63 ALOGD("doCommand: %s", command.c_str());
64 }
65
66 --reply_len; // Ensure we have room to add NUL termination.
67 if (::wifi_command(command.c_str(), reply, &reply_len) != 0) {
68 return false;
69 }
70
71 // Strip off trailing newline.
72 if (reply_len > 0 && reply[reply_len-1] == '\n') {
73 reply[reply_len-1] = '\0';
74 } else {
75 reply[reply_len] = '\0';
76 }
77 return true;
78 }
79
doIntCommand(JNIEnv * env,jstring javaCommand)80 static jint doIntCommand(JNIEnv* env, jstring javaCommand) {
81 char reply[REPLY_BUF_SIZE];
82 if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
83 return -1;
84 }
85 return static_cast<jint>(atoi(reply));
86 }
87
doBooleanCommand(JNIEnv * env,jstring javaCommand)88 static jboolean doBooleanCommand(JNIEnv* env, jstring javaCommand) {
89 char reply[REPLY_BUF_SIZE];
90 if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
91 return JNI_FALSE;
92 }
93 jboolean result = (strcmp(reply, "OK") == 0);
94 if (!result) {
95 ScopedUtfChars command(env, javaCommand);
96 ALOGI("command '%s' returned '%s", command.c_str(), reply);
97 }
98 return result;
99 }
100
101 // Send a command to the supplicant, and return the reply as a String.
doStringCommand(JNIEnv * env,jstring javaCommand)102 static jstring doStringCommand(JNIEnv* env, jstring javaCommand) {
103 char reply[REPLY_BUF_SIZE];
104 if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
105 return NULL;
106 }
107 return env->NewStringUTF(reply);
108 }
109
android_net_wifi_isDriverLoaded(JNIEnv * env,jclass)110 static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jclass)
111 {
112 return (::is_wifi_driver_loaded() == 1);
113 }
114
android_net_wifi_loadDriver(JNIEnv * env,jclass)115 static jboolean android_net_wifi_loadDriver(JNIEnv* env, jclass)
116 {
117 return (::wifi_load_driver() == 0);
118 }
119
android_net_wifi_unloadDriver(JNIEnv * env,jclass)120 static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jclass)
121 {
122 return (::wifi_unload_driver() == 0);
123 }
124
android_net_wifi_startSupplicant(JNIEnv * env,jclass,jboolean p2pSupported)125 static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jclass, jboolean p2pSupported)
126 {
127 return (::wifi_start_supplicant(p2pSupported) == 0);
128 }
129
android_net_wifi_killSupplicant(JNIEnv * env,jclass,jboolean p2pSupported)130 static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jclass, jboolean p2pSupported)
131 {
132 return (::wifi_stop_supplicant(p2pSupported) == 0);
133 }
134
android_net_wifi_connectToSupplicant(JNIEnv * env,jclass)135 static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jclass)
136 {
137 return (::wifi_connect_to_supplicant() == 0);
138 }
139
android_net_wifi_closeSupplicantConnection(JNIEnv * env,jclass)140 static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jclass)
141 {
142 ::wifi_close_supplicant_connection();
143 }
144
android_net_wifi_waitForEvent(JNIEnv * env,jclass)145 static jstring android_net_wifi_waitForEvent(JNIEnv* env, jclass)
146 {
147 char buf[EVENT_BUF_SIZE];
148 int nread = ::wifi_wait_for_event(buf, sizeof buf);
149 if (nread > 0) {
150 return env->NewStringUTF(buf);
151 } else {
152 return NULL;
153 }
154 }
155
android_net_wifi_doBooleanCommand(JNIEnv * env,jclass,jstring javaCommand)156 static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jclass, jstring javaCommand) {
157 return doBooleanCommand(env, javaCommand);
158 }
159
android_net_wifi_doIntCommand(JNIEnv * env,jclass,jstring javaCommand)160 static jint android_net_wifi_doIntCommand(JNIEnv* env, jclass, jstring javaCommand) {
161 return doIntCommand(env, javaCommand);
162 }
163
android_net_wifi_doStringCommand(JNIEnv * env,jclass,jstring javaCommand)164 static jstring android_net_wifi_doStringCommand(JNIEnv* env, jclass, jstring javaCommand) {
165 return doStringCommand(env,javaCommand);
166 }
167
168 /* wifi_hal <==> WifiNative bridge */
169
170 static jclass mCls; /* saved WifiNative object */
171 static JavaVM *mVM; /* saved JVM pointer */
172
173 static const char *WifiHandleVarName = "sWifiHalHandle";
174 static const char *WifiIfaceHandleVarName = "sWifiIfaceHandles";
175
getWifiHandle(JNIHelper & helper,jclass cls)176 wifi_handle getWifiHandle(JNIHelper &helper, jclass cls) {
177 return (wifi_handle) helper.getStaticLongField(cls, WifiHandleVarName);
178 }
179
getIfaceHandle(JNIHelper & helper,jclass cls,jint index)180 wifi_interface_handle getIfaceHandle(JNIHelper &helper, jclass cls, jint index) {
181 return (wifi_interface_handle) helper.getStaticLongArrayField(cls, WifiIfaceHandleVarName, index);
182 }
183
setSSIDField(JNIHelper helper,jobject scanResult,const char * rawSsid)184 jboolean setSSIDField(JNIHelper helper, jobject scanResult, const char *rawSsid) {
185
186 int len = strlen(rawSsid);
187
188 if (len > 0) {
189 JNIObject<jbyteArray> ssidBytes = helper.newByteArray(len);
190 helper.setByteArrayRegion(ssidBytes, 0, len, (jbyte *) rawSsid);
191 jboolean ret = helper.callStaticMethod(mCls,
192 "setSsid", "([BLandroid/net/wifi/ScanResult;)Z", ssidBytes.get(), scanResult);
193 return ret;
194 } else {
195 //empty SSID or SSID start with \0
196 return true;
197 }
198 }
createScanResult(JNIHelper & helper,wifi_scan_result * result,bool fill_ie)199 static JNIObject<jobject> createScanResult(JNIHelper &helper, wifi_scan_result *result,
200 bool fill_ie) {
201 // ALOGD("creating scan result");
202 JNIObject<jobject> scanResult = helper.createObject("android/net/wifi/ScanResult");
203 if (scanResult == NULL) {
204 ALOGE("Error in creating scan result");
205 return JNIObject<jobject>(helper, NULL);
206 }
207
208 ALOGV("setting SSID to %s", result->ssid);
209
210 if (!setSSIDField(helper, scanResult, result->ssid)) {
211 ALOGE("Error on set SSID");
212 return JNIObject<jobject>(helper, NULL);
213 }
214
215 char bssid[32];
216 sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result->bssid[0], result->bssid[1],
217 result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]);
218
219 helper.setStringField(scanResult, "BSSID", bssid);
220
221 helper.setIntField(scanResult, "level", result->rssi);
222 helper.setIntField(scanResult, "frequency", result->channel);
223 helper.setLongField(scanResult, "timestamp", result->ts);
224
225 if (fill_ie) {
226 JNIObject<jbyteArray> elements = helper.newByteArray(result->ie_length);
227 if (elements == NULL) {
228 ALOGE("Error in allocating elements array, length=%d", result->ie_length);
229 return JNIObject<jobject>(helper, NULL);
230 }
231 jbyte * bytes = (jbyte *)&(result->ie_data[0]);
232 helper.setByteArrayRegion(elements, 0, result->ie_length, bytes);
233 helper.setObjectField(scanResult, "bytes", "[B", elements);
234 }
235
236 return scanResult;
237 }
238
set_iface_flags(const char * ifname,bool dev_up)239 int set_iface_flags(const char *ifname, bool dev_up) {
240 struct ifreq ifr;
241 int ret;
242 int sock = socket(PF_INET, SOCK_DGRAM, 0);
243 if (sock < 0) {
244 ALOGD("Bad socket: %d\n", sock);
245 return -errno;
246 }
247
248 //ALOGD("setting interface %s flags (%s)\n", ifname, dev_up ? "UP" : "DOWN");
249
250 memset(&ifr, 0, sizeof(ifr));
251 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
252
253 //ALOGD("reading old value\n");
254
255 if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
256 ret = errno ? -errno : -999;
257 ALOGE("Could not read interface %s flags: %d\n", ifname, errno);
258 close(sock);
259 return ret;
260 } else {
261 //ALOGD("writing new value\n");
262 }
263
264 if (dev_up) {
265 if (ifr.ifr_flags & IFF_UP) {
266 // ALOGD("interface %s is already up\n", ifname);
267 close(sock);
268 return 0;
269 }
270 ifr.ifr_flags |= IFF_UP;
271 } else {
272 if (!(ifr.ifr_flags & IFF_UP)) {
273 // ALOGD("interface %s is already down\n", ifname);
274 close(sock);
275 return 0;
276 }
277 ifr.ifr_flags &= ~IFF_UP;
278 }
279
280 if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
281 ALOGE("Could not set interface %s flags: %d\n", ifname, errno);
282 ret = errno ? -errno : -999;
283 close(sock);
284 return ret;
285 } else {
286 ALOGD("set interface %s flags (%s)\n", ifname, dev_up ? "UP" : "DOWN");
287 }
288 close(sock);
289 return 0;
290 }
291
android_net_wifi_set_interface_up(JNIEnv * env,jclass cls,jboolean up)292 static jboolean android_net_wifi_set_interface_up(JNIEnv* env, jclass cls, jboolean up) {
293 return (set_iface_flags("wlan0", (bool)up) == 0);
294 }
295
android_net_wifi_startHal(JNIEnv * env,jclass cls)296 static jboolean android_net_wifi_startHal(JNIEnv* env, jclass cls) {
297 JNIHelper helper(env);
298 wifi_handle halHandle = getWifiHandle(helper, cls);
299 if (halHandle == NULL) {
300
301 if(init_wifi_stub_hal_func_table(&hal_fn) != 0 ) {
302 ALOGE("Can not initialize the basic function pointer table");
303 return false;
304 }
305
306 wifi_error res = init_wifi_vendor_hal_func_table(&hal_fn);
307 if (res != WIFI_SUCCESS) {
308 ALOGE("Can not initialize the vendor function pointer table");
309 return false;
310 }
311
312 int ret = set_iface_flags("wlan0", true);
313 if(ret != 0) {
314 return false;
315 }
316
317 res = hal_fn.wifi_initialize(&halHandle);
318 if (res == WIFI_SUCCESS) {
319 helper.setStaticLongField(cls, WifiHandleVarName, (jlong)halHandle);
320 ALOGD("Did set static halHandle = %p", halHandle);
321 }
322 env->GetJavaVM(&mVM);
323 mCls = (jclass) env->NewGlobalRef(cls);
324 ALOGD("halHandle = %p, mVM = %p, mCls = %p", halHandle, mVM, mCls);
325 return res == WIFI_SUCCESS;
326 } else {
327 return (set_iface_flags("wlan0", true) == 0);
328 }
329 }
330
android_net_wifi_hal_cleaned_up_handler(wifi_handle handle)331 void android_net_wifi_hal_cleaned_up_handler(wifi_handle handle) {
332 ALOGD("In wifi cleaned up handler");
333
334 JNIHelper helper(mVM);
335 helper.setStaticLongField(mCls, WifiHandleVarName, 0);
336
337 helper.deleteGlobalRef(mCls);
338 mCls = NULL;
339 mVM = NULL;
340 }
341
android_net_wifi_stopHal(JNIEnv * env,jclass cls)342 static void android_net_wifi_stopHal(JNIEnv* env, jclass cls) {
343 ALOGD("In wifi stop Hal");
344
345 JNIHelper helper(env);
346 wifi_handle halHandle = getWifiHandle(helper, cls);
347 if (halHandle == NULL)
348 return;
349
350 ALOGD("halHandle = %p, mVM = %p, mCls = %p", halHandle, mVM, mCls);
351 hal_fn.wifi_cleanup(halHandle, android_net_wifi_hal_cleaned_up_handler);
352 }
353
android_net_wifi_waitForHalEvents(JNIEnv * env,jclass cls)354 static void android_net_wifi_waitForHalEvents(JNIEnv* env, jclass cls) {
355
356 ALOGD("waitForHalEvents called, vm = %p, obj = %p, env = %p", mVM, mCls, env);
357
358 JNIHelper helper(env);
359 wifi_handle halHandle = getWifiHandle(helper, cls);
360 hal_fn.wifi_event_loop(halHandle);
361 set_iface_flags("wlan0", false);
362 }
363
android_net_wifi_getInterfaces(JNIEnv * env,jclass cls)364 static int android_net_wifi_getInterfaces(JNIEnv *env, jclass cls) {
365 int n = 0;
366
367 JNIHelper helper(env);
368
369 wifi_handle halHandle = getWifiHandle(helper, cls);
370 wifi_interface_handle *ifaceHandles = NULL;
371 int result = hal_fn.wifi_get_ifaces(halHandle, &n, &ifaceHandles);
372 if (result < 0) {
373 return result;
374 }
375
376 if (n < 0) {
377 THROW(helper,"android_net_wifi_getInterfaces no interfaces");
378 return 0;
379 }
380
381 if (ifaceHandles == NULL) {
382 THROW(helper,"android_net_wifi_getInterfaces null interface array");
383 return 0;
384 }
385
386 if (n > 8) {
387 THROW(helper,"Too many interfaces");
388 return 0;
389 }
390
391 jlongArray array = (env)->NewLongArray(n);
392 if (array == NULL) {
393 THROW(helper,"Error in accessing array");
394 return 0;
395 }
396
397 jlong elems[8];
398 for (int i = 0; i < n; i++) {
399 elems[i] = reinterpret_cast<jlong>(ifaceHandles[i]);
400 }
401
402 helper.setLongArrayRegion(array, 0, n, elems);
403 helper.setStaticLongArrayField(cls, WifiIfaceHandleVarName, array);
404
405 return (result < 0) ? result : n;
406 }
407
android_net_wifi_getInterfaceName(JNIEnv * env,jclass cls,jint i)408 static jstring android_net_wifi_getInterfaceName(JNIEnv *env, jclass cls, jint i) {
409
410 char buf[EVENT_BUF_SIZE];
411
412 JNIHelper helper(env);
413
414 jlong value = helper.getStaticLongArrayField(cls, WifiIfaceHandleVarName, i);
415 wifi_interface_handle handle = (wifi_interface_handle) value;
416 int result = hal_fn.wifi_get_iface_name(handle, buf, sizeof(buf));
417 if (result < 0) {
418 return NULL;
419 } else {
420 JNIObject<jstring> name = helper.newStringUTF(buf);
421 return name.detach();
422 }
423 }
424
425
onScanEvent(wifi_request_id id,wifi_scan_event event)426 static void onScanEvent(wifi_request_id id, wifi_scan_event event) {
427
428 JNIHelper helper(mVM);
429
430 // ALOGD("onScanStatus called, vm = %p, obj = %p, env = %p", mVM, mCls, env);
431
432 helper.reportEvent(mCls, "onScanStatus", "(II)V", id, event);
433 }
434
onFullScanResult(wifi_request_id id,wifi_scan_result * result,unsigned buckets_scanned)435 static void onFullScanResult(wifi_request_id id, wifi_scan_result *result,
436 unsigned buckets_scanned) {
437
438 JNIHelper helper(mVM);
439
440 //ALOGD("onFullScanResult called, vm = %p, obj = %p, env = %p", mVM, mCls, env);
441
442 JNIObject<jobject> scanResult = createScanResult(helper, result, true);
443
444 if (scanResult == NULL) {
445 return;
446 }
447
448 helper.reportEvent(mCls, "onFullScanResult", "(ILandroid/net/wifi/ScanResult;II)V", id,
449 scanResult.get(), buckets_scanned, (jint) result->capability);
450 }
451
android_net_wifi_startScan(JNIEnv * env,jclass cls,jint iface,jint id,jobject settings)452 static jboolean android_net_wifi_startScan(
453 JNIEnv *env, jclass cls, jint iface, jint id, jobject settings) {
454
455 JNIHelper helper(env);
456 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
457 // ALOGD("starting scan on interface[%d] = %p", iface, handle);
458
459 wifi_scan_cmd_params params;
460 memset(¶ms, 0, sizeof(params));
461
462 params.base_period = helper.getIntField(settings, "base_period_ms");
463 params.max_ap_per_scan = helper.getIntField(settings, "max_ap_per_scan");
464 params.report_threshold_percent = helper.getIntField(settings, "report_threshold_percent");
465 params.report_threshold_num_scans = helper.getIntField(settings, "report_threshold_num_scans");
466
467 ALOGD("Initialized common fields %d, %d, %d, %d", params.base_period, params.max_ap_per_scan,
468 params.report_threshold_percent, params.report_threshold_num_scans);
469
470 const char *bucket_array_type = "[Lcom/android/server/wifi/WifiNative$BucketSettings;";
471 const char *channel_array_type = "[Lcom/android/server/wifi/WifiNative$ChannelSettings;";
472
473 params.num_buckets = helper.getIntField(settings, "num_buckets");
474
475 // ALOGD("Initialized num_buckets to %d", params.num_buckets);
476
477 for (int i = 0; i < params.num_buckets; i++) {
478 JNIObject<jobject> bucket = helper.getObjectArrayField(
479 settings, "buckets", bucket_array_type, i);
480
481 params.buckets[i].bucket = helper.getIntField(bucket, "bucket");
482 params.buckets[i].band = (wifi_band) helper.getIntField(bucket, "band");
483 params.buckets[i].period = helper.getIntField(bucket, "period_ms");
484 params.buckets[i].max_period = helper.getIntField(bucket, "max_period_ms");
485 // Although HAL API allows configurable base value for the truncated
486 // exponential back off scan. Native API and above support only
487 // truncated binary exponential back off scan.
488 // Hard code value of base to 2 here.
489 params.buckets[i].base = 2;
490 params.buckets[i].step_count = helper.getIntField(bucket, "step_count");
491
492 int report_events = helper.getIntField(bucket, "report_events");
493 params.buckets[i].report_events = report_events;
494
495 if (DBG) {
496 ALOGD("bucket[%d] = %d:%d:%d:%d:%d:%d:%d", i, params.buckets[i].bucket,
497 params.buckets[i].band, params.buckets[i].period,
498 params.buckets[i].max_period, params.buckets[i].base,
499 params.buckets[i].step_count, report_events);
500 }
501
502 params.buckets[i].num_channels = helper.getIntField(bucket, "num_channels");
503 // ALOGD("Initialized num_channels to %d", params.buckets[i].num_channels);
504
505 for (int j = 0; j < params.buckets[i].num_channels; j++) {
506 JNIObject<jobject> channel = helper.getObjectArrayField(
507 bucket, "channels", channel_array_type, j);
508
509 params.buckets[i].channels[j].channel = helper.getIntField(channel, "frequency");
510 params.buckets[i].channels[j].dwellTimeMs = helper.getIntField(channel, "dwell_time_ms");
511
512 bool passive = helper.getBoolField(channel, "passive");
513 params.buckets[i].channels[j].passive = (passive ? 1 : 0);
514
515 // ALOGD("Initialized channel %d", params.buckets[i].channels[j].channel);
516 }
517 }
518
519 // ALOGD("Initialized all fields");
520
521 wifi_scan_result_handler handler;
522 memset(&handler, 0, sizeof(handler));
523 handler.on_full_scan_result = &onFullScanResult;
524 handler.on_scan_event = &onScanEvent;
525
526 return hal_fn.wifi_start_gscan(id, handle, params, handler) == WIFI_SUCCESS;
527 }
528
android_net_wifi_stopScan(JNIEnv * env,jclass cls,jint iface,jint id)529 static jboolean android_net_wifi_stopScan(JNIEnv *env, jclass cls, jint iface, jint id) {
530
531 JNIHelper helper(env);
532 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
533 // ALOGD("stopping scan on interface[%d] = %p", iface, handle);
534
535 return hal_fn.wifi_stop_gscan(id, handle) == WIFI_SUCCESS;
536 }
537
compare_scan_result_timestamp(const void * v1,const void * v2)538 static int compare_scan_result_timestamp(const void *v1, const void *v2) {
539 const wifi_scan_result *result1 = static_cast<const wifi_scan_result *>(v1);
540 const wifi_scan_result *result2 = static_cast<const wifi_scan_result *>(v2);
541 return result1->ts - result2->ts;
542 }
543
android_net_wifi_getScanResults(JNIEnv * env,jclass cls,jint iface,jboolean flush)544 static jobject android_net_wifi_getScanResults(
545 JNIEnv *env, jclass cls, jint iface, jboolean flush) {
546
547 JNIHelper helper(env);
548 wifi_cached_scan_results scan_data[64];
549 int num_scan_data = 64;
550
551 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
552 // ALOGD("getting scan results on interface[%d] = %p", iface, handle);
553
554 byte b = flush ? 0xFF : 0;
555 int result = hal_fn.wifi_get_cached_gscan_results(handle, b, num_scan_data, scan_data, &num_scan_data);
556 if (result == WIFI_SUCCESS) {
557 JNIObject<jobjectArray> scanData = helper.createObjectArray(
558 "android/net/wifi/WifiScanner$ScanData", num_scan_data);
559 if (scanData == NULL) {
560 ALOGE("Error in allocating array of scanData for getScanResults, length=%d",
561 num_scan_data);
562 return NULL;
563 }
564
565 for (int i = 0; i < num_scan_data; i++) {
566
567 JNIObject<jobject> data = helper.createObject("android/net/wifi/WifiScanner$ScanData");
568 if (data == NULL) {
569 ALOGE("Error in allocating scanData for getScanResults");
570 return NULL;
571 }
572
573 helper.setIntField(data, "mId", scan_data[i].scan_id);
574 helper.setIntField(data, "mFlags", scan_data[i].flags);
575 helper.setIntField(data, "mBucketsScanned", scan_data[i].buckets_scanned);
576
577 /* sort all scan results by timestamp */
578 qsort(scan_data[i].results, scan_data[i].num_results,
579 sizeof(wifi_scan_result), compare_scan_result_timestamp);
580
581 JNIObject<jobjectArray> scanResults = helper.createObjectArray(
582 "android/net/wifi/ScanResult", scan_data[i].num_results);
583 if (scanResults == NULL) {
584 ALOGE("Error in allocating scanResult array for getScanResults, length=%d",
585 scan_data[i].num_results);
586 return NULL;
587 }
588
589 wifi_scan_result *results = scan_data[i].results;
590 for (int j = 0; j < scan_data[i].num_results; j++) {
591
592 JNIObject<jobject> scanResult = createScanResult(helper, &results[j], false);
593 if (scanResult == NULL) {
594 ALOGE("Error in creating scan result for getScanResults");
595 return NULL;
596 }
597
598 helper.setObjectArrayElement(scanResults, j, scanResult);
599 }
600
601 helper.setObjectField(data, "mResults", "[Landroid/net/wifi/ScanResult;", scanResults);
602 helper.setObjectArrayElement(scanData, i, data);
603 }
604
605 // ALOGD("retrieved %d scan data from interface[%d] = %p", num_scan_data, iface, handle);
606 return scanData.detach();
607 } else {
608 return NULL;
609 }
610 }
611
612
android_net_wifi_getScanCapabilities(JNIEnv * env,jclass cls,jint iface,jobject capabilities)613 static jboolean android_net_wifi_getScanCapabilities(
614 JNIEnv *env, jclass cls, jint iface, jobject capabilities) {
615
616 JNIHelper helper(env);
617 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
618 // ALOGD("getting scan capabilities on interface[%d] = %p", iface, handle);
619
620 wifi_gscan_capabilities c;
621 memset(&c, 0, sizeof(c));
622 int result = hal_fn.wifi_get_gscan_capabilities(handle, &c);
623 if (result != WIFI_SUCCESS) {
624 ALOGD("failed to get capabilities : %d", result);
625 return JNI_FALSE;
626 }
627
628 helper.setIntField(capabilities, "max_scan_cache_size", c.max_scan_cache_size);
629 helper.setIntField(capabilities, "max_scan_buckets", c.max_scan_buckets);
630 helper.setIntField(capabilities, "max_ap_cache_per_scan", c.max_ap_cache_per_scan);
631 helper.setIntField(capabilities, "max_rssi_sample_size", c.max_rssi_sample_size);
632 helper.setIntField(capabilities, "max_scan_reporting_threshold", c.max_scan_reporting_threshold);
633 helper.setIntField(capabilities, "max_hotlist_bssids", c.max_hotlist_bssids);
634 helper.setIntField(capabilities, "max_significant_wifi_change_aps",
635 c.max_significant_wifi_change_aps);
636 helper.setIntField(capabilities, "max_bssid_history_entries", c.max_bssid_history_entries);
637 helper.setIntField(capabilities, "max_number_epno_networks", c.max_number_epno_networks);
638 helper.setIntField(capabilities, "max_number_epno_networks_by_ssid",
639 c.max_number_epno_networks_by_ssid);
640 helper.setIntField(capabilities, "max_number_of_white_listed_ssid",
641 c.max_number_of_white_listed_ssid);
642
643 return JNI_TRUE;
644 }
645
646
parseHexChar(char ch)647 static byte parseHexChar(char ch) {
648 if (isdigit(ch))
649 return ch - '0';
650 else if ('A' <= ch && ch <= 'F')
651 return ch - 'A' + 10;
652 else if ('a' <= ch && ch <= 'f')
653 return ch - 'a' + 10;
654 else {
655 ALOGE("invalid character in bssid %c", ch);
656 return 0;
657 }
658 }
659
parseHexByte(const char * & str)660 static byte parseHexByte(const char * &str) {
661 if (str[0] == '\0') {
662 ALOGE("Passed an empty string");
663 return 0;
664 }
665 byte b = parseHexChar(str[0]);
666 if (str[1] == '\0' || str[1] == ':') {
667 str ++;
668 } else {
669 b = b << 4 | parseHexChar(str[1]);
670 str += 2;
671 }
672
673 // Skip trailing delimiter if not at the end of the string.
674 if (str[0] != '\0') {
675 str++;
676 }
677 return b;
678 }
679
parseMacAddress(const char * str,mac_addr addr)680 static void parseMacAddress(const char *str, mac_addr addr) {
681 addr[0] = parseHexByte(str);
682 addr[1] = parseHexByte(str);
683 addr[2] = parseHexByte(str);
684 addr[3] = parseHexByte(str);
685 addr[4] = parseHexByte(str);
686 addr[5] = parseHexByte(str);
687 }
688
parseMacAddress(JNIEnv * env,jobject obj,mac_addr addr)689 static bool parseMacAddress(JNIEnv *env, jobject obj, mac_addr addr) {
690 JNIHelper helper(env);
691 JNIObject<jstring> macAddrString = helper.getStringField(obj, "bssid");
692 if (macAddrString == NULL) {
693 ALOGE("Error getting bssid field");
694 return false;
695 }
696
697 ScopedUtfChars chars(env, macAddrString);
698 const char *bssid = chars.c_str();
699 if (bssid == NULL) {
700 ALOGE("Error getting bssid");
701 return false;
702 }
703
704 parseMacAddress(bssid, addr);
705 return true;
706 }
707
onHotlistApFound(wifi_request_id id,unsigned num_results,wifi_scan_result * results)708 static void onHotlistApFound(wifi_request_id id,
709 unsigned num_results, wifi_scan_result *results) {
710
711 JNIHelper helper(mVM);
712 ALOGD("onHotlistApFound called, vm = %p, obj = %p, num_results = %d", mVM, mCls, num_results);
713
714 JNIObject<jobjectArray> scanResults = helper.newObjectArray(num_results,
715 "android/net/wifi/ScanResult", NULL);
716 if (scanResults == NULL) {
717 ALOGE("Error in allocating ScanResult array in onHotlistApFound, length=%d", num_results);
718 return;
719 }
720
721 for (unsigned i = 0; i < num_results; i++) {
722
723 JNIObject<jobject> scanResult = createScanResult(helper, &results[i], false);
724 if (scanResult == NULL) {
725 ALOGE("Error in creating scan result in onHotlistApFound");
726 return;
727 }
728
729 helper.setObjectArrayElement(scanResults, i, scanResult);
730
731 ALOGD("Found AP %32s", results[i].ssid);
732 }
733
734 helper.reportEvent(mCls, "onHotlistApFound", "(I[Landroid/net/wifi/ScanResult;)V",
735 id, scanResults.get());
736 }
737
onHotlistApLost(wifi_request_id id,unsigned num_results,wifi_scan_result * results)738 static void onHotlistApLost(wifi_request_id id,
739 unsigned num_results, wifi_scan_result *results) {
740
741 JNIHelper helper(mVM);
742 ALOGD("onHotlistApLost called, vm = %p, obj = %p, num_results = %d", mVM, mCls, num_results);
743
744 JNIObject<jobjectArray> scanResults = helper.newObjectArray(num_results,
745 "android/net/wifi/ScanResult", NULL);
746 if (scanResults == NULL) {
747 ALOGE("Error in allocating ScanResult array onHotlistApLost, length=%d", num_results);
748 return;
749 }
750
751 for (unsigned i = 0; i < num_results; i++) {
752
753 JNIObject<jobject> scanResult = createScanResult(helper, &results[i], false);
754 if (scanResult == NULL) {
755 ALOGE("Error in creating scan result in onHotlistApLost");
756 return;
757 }
758
759 helper.setObjectArrayElement(scanResults, i, scanResult);
760
761 ALOGD("Lost AP %32s", results[i].ssid);
762 }
763
764 helper.reportEvent(mCls, "onHotlistApLost", "(I[Landroid/net/wifi/ScanResult;)V",
765 id, scanResults.get());
766 }
767
768
android_net_wifi_setHotlist(JNIEnv * env,jclass cls,jint iface,jint id,jobject ap)769 static jboolean android_net_wifi_setHotlist(
770 JNIEnv *env, jclass cls, jint iface, jint id, jobject ap) {
771
772 JNIHelper helper(env);
773 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
774 ALOGD("setting hotlist on interface[%d] = %p", iface, handle);
775
776 wifi_bssid_hotlist_params params;
777 memset(¶ms, 0, sizeof(params));
778
779 params.lost_ap_sample_size = helper.getIntField(ap, "apLostThreshold");
780
781 JNIObject<jobjectArray> array = helper.getArrayField(
782 ap, "bssidInfos", "[Landroid/net/wifi/WifiScanner$BssidInfo;");
783 params.num_bssid = helper.getArrayLength(array);
784
785 if (params.num_bssid == 0) {
786 ALOGE("setHotlist array length was 0");
787 return false;
788 }
789
790 for (int i = 0; i < params.num_bssid; i++) {
791 JNIObject<jobject> objAp = helper.getObjectArrayElement(array, i);
792
793 JNIObject<jstring> macAddrString = helper.getStringField(objAp, "bssid");
794 if (macAddrString == NULL) {
795 ALOGE("Error getting bssid field");
796 return false;
797 }
798
799 ScopedUtfChars chars(env, macAddrString);
800 const char *bssid = chars.c_str();
801 if (bssid == NULL) {
802 ALOGE("Error getting bssid");
803 return false;
804 }
805 parseMacAddress(bssid, params.ap[i].bssid);
806
807 mac_addr addr;
808 memcpy(addr, params.ap[i].bssid, sizeof(mac_addr));
809
810 char bssidOut[32];
811 sprintf(bssidOut, "%0x:%0x:%0x:%0x:%0x:%0x", addr[0], addr[1],
812 addr[2], addr[3], addr[4], addr[5]);
813
814 ALOGD("Added bssid %s", bssidOut);
815
816 params.ap[i].low = helper.getIntField(objAp, "low");
817 params.ap[i].high = helper.getIntField(objAp, "high");
818 }
819
820 wifi_hotlist_ap_found_handler handler;
821 memset(&handler, 0, sizeof(handler));
822
823 handler.on_hotlist_ap_found = &onHotlistApFound;
824 handler.on_hotlist_ap_lost = &onHotlistApLost;
825 return hal_fn.wifi_set_bssid_hotlist(id, handle, params, handler) == WIFI_SUCCESS;
826 }
827
android_net_wifi_resetHotlist(JNIEnv * env,jclass cls,jint iface,jint id)828 static jboolean android_net_wifi_resetHotlist(JNIEnv *env, jclass cls, jint iface, jint id) {
829
830 JNIHelper helper(env);
831 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
832 ALOGD("resetting hotlist on interface[%d] = %p", iface, handle);
833
834 return hal_fn.wifi_reset_bssid_hotlist(id, handle) == WIFI_SUCCESS;
835 }
836
onSignificantWifiChange(wifi_request_id id,unsigned num_results,wifi_significant_change_result ** results)837 void onSignificantWifiChange(wifi_request_id id,
838 unsigned num_results, wifi_significant_change_result **results) {
839
840 JNIHelper helper(mVM);
841
842 ALOGD("onSignificantWifiChange called, vm = %p, obj = %p", mVM, mCls);
843
844 JNIObject<jobjectArray> scanResults = helper.newObjectArray(
845 num_results, "android/net/wifi/ScanResult", NULL);
846 if (scanResults == NULL) {
847 ALOGE("Error in allocating ScanResult array in onSignificantWifiChange, length=%d",
848 num_results);
849 return;
850 }
851
852 for (unsigned i = 0; i < num_results; i++) {
853
854 wifi_significant_change_result &result = *(results[i]);
855
856 JNIObject<jobject> scanResult = helper.createObject("android/net/wifi/ScanResult");
857 if (scanResult == NULL) {
858 ALOGE("Error in creating scan result in onSignificantWifiChange");
859 return;
860 }
861
862 // helper.setStringField(scanResult, "SSID", results[i].ssid);
863
864 char bssid[32];
865 sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result.bssid[0], result.bssid[1],
866 result.bssid[2], result.bssid[3], result.bssid[4], result.bssid[5]);
867
868 helper.setStringField(scanResult, "BSSID", bssid);
869
870 helper.setIntField(scanResult, "level", result.rssi[0]);
871 helper.setIntField(scanResult, "frequency", result.channel);
872 // helper.setLongField(scanResult, "timestamp", result.ts);
873
874 helper.setObjectArrayElement(scanResults, i, scanResult);
875 }
876
877 helper.reportEvent(mCls, "onSignificantWifiChange", "(I[Landroid/net/wifi/ScanResult;)V",
878 id, scanResults.get());
879
880 }
881
android_net_wifi_trackSignificantWifiChange(JNIEnv * env,jclass cls,jint iface,jint id,jobject settings)882 static jboolean android_net_wifi_trackSignificantWifiChange(
883 JNIEnv *env, jclass cls, jint iface, jint id, jobject settings) {
884
885 JNIHelper helper(env);
886 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
887 ALOGD("tracking significant wifi change on interface[%d] = %p", iface, handle);
888
889 wifi_significant_change_params params;
890 memset(¶ms, 0, sizeof(params));
891
892 params.rssi_sample_size = helper.getIntField(settings, "rssiSampleSize");
893 params.lost_ap_sample_size = helper.getIntField(settings, "lostApSampleSize");
894 params.min_breaching = helper.getIntField(settings, "minApsBreachingThreshold");
895
896 const char *bssid_info_array_type = "[Landroid/net/wifi/WifiScanner$BssidInfo;";
897 JNIObject<jobjectArray> bssids = helper.getArrayField(
898 settings, "bssidInfos", bssid_info_array_type);
899 params.num_bssid = helper.getArrayLength(bssids);
900
901 if (params.num_bssid == 0) {
902 ALOGE("BssidInfo array length was 0");
903 return false;
904 }
905
906 ALOGD("Initialized common fields %d, %d, %d, %d", params.rssi_sample_size,
907 params.lost_ap_sample_size, params.min_breaching, params.num_bssid);
908
909 for (int i = 0; i < params.num_bssid; i++) {
910 JNIObject<jobject> objAp = helper.getObjectArrayElement(bssids, i);
911
912 JNIObject<jstring> macAddrString = helper.getStringField(objAp, "bssid");
913 if (macAddrString == NULL) {
914 ALOGE("Error getting bssid field");
915 return false;
916 }
917
918 ScopedUtfChars chars(env, macAddrString.get());
919 const char *bssid = chars.c_str();
920 if (bssid == NULL) {
921 ALOGE("Error getting bssid");
922 return false;
923 }
924
925 mac_addr addr;
926 parseMacAddress(bssid, addr);
927 memcpy(params.ap[i].bssid, addr, sizeof(mac_addr));
928
929 char bssidOut[32];
930 sprintf(bssidOut, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1],
931 addr[2], addr[3], addr[4], addr[5]);
932
933 params.ap[i].low = helper.getIntField(objAp, "low");
934 params.ap[i].high = helper.getIntField(objAp, "high");
935
936 ALOGD("Added bssid %s, [%04d, %04d]", bssidOut, params.ap[i].low, params.ap[i].high);
937 }
938
939 ALOGD("Added %d bssids", params.num_bssid);
940
941 wifi_significant_change_handler handler;
942 memset(&handler, 0, sizeof(handler));
943
944 handler.on_significant_change = &onSignificantWifiChange;
945 return hal_fn.wifi_set_significant_change_handler(id, handle, params, handler) == WIFI_SUCCESS;
946 }
947
android_net_wifi_untrackSignificantWifiChange(JNIEnv * env,jclass cls,jint iface,jint id)948 static jboolean android_net_wifi_untrackSignificantWifiChange(
949 JNIEnv *env, jclass cls, jint iface, jint id) {
950
951 JNIHelper helper(env);
952 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
953 ALOGD("resetting significant wifi change on interface[%d] = %p", iface, handle);
954
955 return hal_fn.wifi_reset_significant_change_handler(id, handle) == WIFI_SUCCESS;
956 }
957
958 wifi_iface_stat link_stat;
959 wifi_radio_stat radio_stat; // L release has support for only one radio
960 u32 *tx_time_per_level_arr = 0;
961 // Let's cache the supported feature set to avoid unnecessary HAL invocations.
962 feature_set cached_feature_set = 0;
963
isTxLevelStatsPresent(wifi_radio_stat * radio_stats)964 bool isTxLevelStatsPresent(wifi_radio_stat *radio_stats) {
965 if (IS_SUPPORTED_FEATURE(WIFI_FEATURE_TX_TRANSMIT_POWER, cached_feature_set)) {
966 if(radio_stats->tx_time_per_levels != 0 && radio_stats->num_tx_levels > 0) {
967 return true;
968 } else {
969 ALOGE("Ignoring invalid tx_level info in radio_stats");
970 }
971 }
972 return false;
973 }
974
onLinkStatsResults(wifi_request_id id,wifi_iface_stat * iface_stat,int num_radios,wifi_radio_stat * radio_stats)975 void onLinkStatsResults(wifi_request_id id, wifi_iface_stat *iface_stat,
976 int num_radios, wifi_radio_stat *radio_stats)
977 {
978 if (iface_stat != 0) {
979 memcpy(&link_stat, iface_stat, sizeof(wifi_iface_stat));
980 } else {
981 memset(&link_stat, 0, sizeof(wifi_iface_stat));
982 }
983
984 if (num_radios > 0 && radio_stats != 0) {
985 memcpy(&radio_stat, radio_stats, sizeof(wifi_radio_stat));
986 if (isTxLevelStatsPresent(radio_stats)) {
987 // This realloc should be a no-op after the first allocation because for a given
988 // device, the number of power levels should not change.
989 u32 arr_size = sizeof(u32) * radio_stats->num_tx_levels;
990 tx_time_per_level_arr = (u32 *)realloc(tx_time_per_level_arr, arr_size);
991 memcpy(tx_time_per_level_arr, radio_stats->tx_time_per_levels, arr_size);
992 radio_stat.tx_time_per_levels = tx_time_per_level_arr;
993 } else {
994 radio_stat.num_tx_levels = 0;
995 radio_stat.tx_time_per_levels = 0;
996 }
997 } else {
998 memset(&radio_stat, 0, sizeof(wifi_radio_stat));
999 }
1000 }
1001
android_net_wifi_setLinkLayerStats(JNIEnv * env,jclass cls,jint iface,int enable)1002 static void android_net_wifi_setLinkLayerStats (JNIEnv *env, jclass cls, jint iface, int enable) {
1003 JNIHelper helper(env);
1004 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1005
1006 wifi_link_layer_params params;
1007 params.aggressive_statistics_gathering = enable;
1008 params.mpdu_size_threshold = 128;
1009
1010 ALOGD("android_net_wifi_setLinkLayerStats: %u\n", enable);
1011
1012 hal_fn.wifi_set_link_stats(handle, params);
1013 }
1014
android_net_wifi_getLinkLayerStats(JNIEnv * env,jclass cls,jint iface)1015 static jobject android_net_wifi_getLinkLayerStats (JNIEnv *env, jclass cls, jint iface) {
1016
1017 JNIHelper helper(env);
1018 wifi_stats_result_handler handler;
1019 memset(&handler, 0, sizeof(handler));
1020 handler.on_link_stats_results = &onLinkStatsResults;
1021 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1022 int result;
1023 // Cache the features supported by the device to determine if tx level stats are present or not
1024 if (cached_feature_set == 0) {
1025 result = hal_fn.wifi_get_supported_feature_set(handle, &cached_feature_set);
1026 if (result != WIFI_SUCCESS) {
1027 cached_feature_set = 0;
1028 }
1029 }
1030
1031 result = hal_fn.wifi_get_link_stats(0, handle, handler);
1032 if (result < 0) {
1033 ALOGE("android_net_wifi_getLinkLayerStats: failed to get link statistics\n");
1034 return NULL;
1035 }
1036
1037 JNIObject<jobject> wifiLinkLayerStats = helper.createObject(
1038 "android/net/wifi/WifiLinkLayerStats");
1039 if (wifiLinkLayerStats == NULL) {
1040 ALOGE("Error in allocating wifiLinkLayerStats");
1041 return NULL;
1042 }
1043
1044 JNIObject<jintArray> tx_time_per_level = helper.newIntArray(radio_stat.num_tx_levels);
1045 if (tx_time_per_level == NULL) {
1046 ALOGE("Error in allocating wifiLinkLayerStats");
1047 return NULL;
1048 }
1049
1050 helper.setIntField(wifiLinkLayerStats, "beacon_rx", link_stat.beacon_rx);
1051 helper.setIntField(wifiLinkLayerStats, "rssi_mgmt", link_stat.rssi_mgmt);
1052 helper.setLongField(wifiLinkLayerStats, "rxmpdu_be", link_stat.ac[WIFI_AC_BE].rx_mpdu);
1053 helper.setLongField(wifiLinkLayerStats, "rxmpdu_bk", link_stat.ac[WIFI_AC_BK].rx_mpdu);
1054 helper.setLongField(wifiLinkLayerStats, "rxmpdu_vi", link_stat.ac[WIFI_AC_VI].rx_mpdu);
1055 helper.setLongField(wifiLinkLayerStats, "rxmpdu_vo", link_stat.ac[WIFI_AC_VO].rx_mpdu);
1056 helper.setLongField(wifiLinkLayerStats, "txmpdu_be", link_stat.ac[WIFI_AC_BE].tx_mpdu);
1057 helper.setLongField(wifiLinkLayerStats, "txmpdu_bk", link_stat.ac[WIFI_AC_BK].tx_mpdu);
1058 helper.setLongField(wifiLinkLayerStats, "txmpdu_vi", link_stat.ac[WIFI_AC_VI].tx_mpdu);
1059 helper.setLongField(wifiLinkLayerStats, "txmpdu_vo", link_stat.ac[WIFI_AC_VO].tx_mpdu);
1060 helper.setLongField(wifiLinkLayerStats, "lostmpdu_be", link_stat.ac[WIFI_AC_BE].mpdu_lost);
1061 helper.setLongField(wifiLinkLayerStats, "lostmpdu_bk", link_stat.ac[WIFI_AC_BK].mpdu_lost);
1062 helper.setLongField(wifiLinkLayerStats, "lostmpdu_vi", link_stat.ac[WIFI_AC_VI].mpdu_lost);
1063 helper.setLongField(wifiLinkLayerStats, "lostmpdu_vo", link_stat.ac[WIFI_AC_VO].mpdu_lost);
1064 helper.setLongField(wifiLinkLayerStats, "retries_be", link_stat.ac[WIFI_AC_BE].retries);
1065 helper.setLongField(wifiLinkLayerStats, "retries_bk", link_stat.ac[WIFI_AC_BK].retries);
1066 helper.setLongField(wifiLinkLayerStats, "retries_vi", link_stat.ac[WIFI_AC_VI].retries);
1067 helper.setLongField(wifiLinkLayerStats, "retries_vo", link_stat.ac[WIFI_AC_VO].retries);
1068
1069 helper.setIntField(wifiLinkLayerStats, "on_time", radio_stat.on_time);
1070 helper.setIntField(wifiLinkLayerStats, "tx_time", radio_stat.tx_time);
1071 helper.setIntField(wifiLinkLayerStats, "rx_time", radio_stat.rx_time);
1072 helper.setIntField(wifiLinkLayerStats, "on_time_scan", radio_stat.on_time_scan);
1073 if (radio_stat.tx_time_per_levels != 0) {
1074 helper.setIntArrayRegion(tx_time_per_level, 0, radio_stat.num_tx_levels,
1075 (jint *)radio_stat.tx_time_per_levels);
1076 }
1077 helper.setObjectField(wifiLinkLayerStats, "tx_time_per_level", "[I", tx_time_per_level);
1078
1079
1080 return wifiLinkLayerStats.detach();
1081 }
1082
android_net_wifi_getSupportedFeatures(JNIEnv * env,jclass cls,jint iface)1083 static jint android_net_wifi_getSupportedFeatures(JNIEnv *env, jclass cls, jint iface) {
1084
1085 JNIHelper helper(env);
1086 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1087 feature_set set = 0;
1088
1089 wifi_error result = WIFI_SUCCESS;
1090 /*
1091 set = WIFI_FEATURE_INFRA
1092 | WIFI_FEATURE_INFRA_5G
1093 | WIFI_FEATURE_HOTSPOT
1094 | WIFI_FEATURE_P2P
1095 | WIFI_FEATURE_SOFT_AP
1096 | WIFI_FEATURE_GSCAN
1097 | WIFI_FEATURE_PNO
1098 | WIFI_FEATURE_TDLS
1099 | WIFI_FEATURE_EPR;
1100 */
1101
1102 result = hal_fn.wifi_get_supported_feature_set(handle, &set);
1103 if (result == WIFI_SUCCESS) {
1104 // ALOGD("wifi_get_supported_feature_set returned set = 0x%x", set);
1105 return set;
1106 } else {
1107 ALOGE("wifi_get_supported_feature_set returned error = 0x%x", result);
1108 return 0;
1109 }
1110 }
1111
onRttResults(wifi_request_id id,unsigned num_results,wifi_rtt_result * results[])1112 static void onRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* results[]) {
1113
1114 JNIHelper helper(mVM);
1115
1116 ALOGD("onRttResults called, vm = %p, obj = %p", mVM, mCls);
1117
1118 JNIObject<jobjectArray> rttResults = helper.newObjectArray(
1119 num_results, "android/net/wifi/RttManager$RttResult", NULL);
1120 if (rttResults == NULL) {
1121 ALOGE("Error in allocating RttResult array in onRttResults, length=%d", num_results);
1122 return;
1123 }
1124
1125 for (unsigned i = 0; i < num_results; i++) {
1126
1127 wifi_rtt_result *result = results[i];
1128
1129 JNIObject<jobject> rttResult = helper.createObject("android/net/wifi/RttManager$RttResult");
1130 if (rttResult == NULL) {
1131 ALOGE("Error in creating rtt result in onRttResults");
1132 return;
1133 }
1134
1135 char bssid[32];
1136 sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result->addr[0], result->addr[1],
1137 result->addr[2], result->addr[3], result->addr[4], result->addr[5]);
1138
1139 helper.setStringField(rttResult, "bssid", bssid);
1140 helper.setIntField( rttResult, "burstNumber", result->burst_num);
1141 helper.setIntField( rttResult, "measurementFrameNumber", result->measurement_number);
1142 helper.setIntField( rttResult, "successMeasurementFrameNumber", result->success_number);
1143 helper.setIntField(rttResult, "frameNumberPerBurstPeer", result->number_per_burst_peer);
1144 helper.setIntField( rttResult, "status", result->status);
1145 helper.setIntField( rttResult, "measurementType", result->type);
1146 helper.setIntField(rttResult, "retryAfterDuration", result->retry_after_duration);
1147 helper.setLongField(rttResult, "ts", result->ts);
1148 helper.setIntField( rttResult, "rssi", result->rssi);
1149 helper.setIntField( rttResult, "rssiSpread", result->rssi_spread);
1150 helper.setIntField( rttResult, "txRate", result->tx_rate.bitrate);
1151 helper.setIntField( rttResult, "rxRate", result->rx_rate.bitrate);
1152 helper.setLongField(rttResult, "rtt", result->rtt);
1153 helper.setLongField(rttResult, "rttStandardDeviation", result->rtt_sd);
1154 helper.setIntField( rttResult, "distance", result->distance_mm / 10);
1155 helper.setIntField( rttResult, "distanceStandardDeviation", result->distance_sd_mm / 10);
1156 helper.setIntField( rttResult, "distanceSpread", result->distance_spread_mm / 10);
1157 helper.setIntField( rttResult, "burstDuration", result->burst_duration);
1158 helper.setIntField( rttResult, "negotiatedBurstNum", result->negotiated_burst_num);
1159
1160 JNIObject<jobject> LCI = helper.createObject(
1161 "android/net/wifi/RttManager$WifiInformationElement");
1162 if (result->LCI != NULL && result->LCI->len > 0) {
1163 ALOGD("Add LCI in result");
1164 helper.setByteField(LCI, "id", result->LCI->id);
1165 JNIObject<jbyteArray> elements = helper.newByteArray(result->LCI->len);
1166 jbyte *bytes = (jbyte *)&(result->LCI->data[0]);
1167 helper.setByteArrayRegion(elements, 0, result->LCI->len, bytes);
1168 helper.setObjectField(LCI, "data", "[B", elements);
1169 } else {
1170 ALOGD("No LCI in result");
1171 helper.setByteField(LCI, "id", (byte)(0xff));
1172 }
1173 helper.setObjectField(rttResult, "LCI",
1174 "Landroid/net/wifi/RttManager$WifiInformationElement;", LCI);
1175
1176 JNIObject<jobject> LCR = helper.createObject(
1177 "android/net/wifi/RttManager$WifiInformationElement");
1178 if (result->LCR != NULL && result->LCR->len > 0) {
1179 ALOGD("Add LCR in result");
1180 helper.setByteField(LCR, "id", result->LCR->id);
1181 JNIObject<jbyteArray> elements = helper.newByteArray(result->LCI->len);
1182 jbyte *bytes = (jbyte *)&(result->LCR->data[0]);
1183 helper.setByteArrayRegion(elements, 0, result->LCI->len, bytes);
1184 helper.setObjectField(LCR, "data", "[B", elements);
1185 } else {
1186 ALOGD("No LCR in result");
1187 helper.setByteField(LCR, "id", (byte)(0xff));
1188 }
1189 helper.setObjectField(rttResult, "LCR",
1190 "Landroid/net/wifi/RttManager$WifiInformationElement;", LCR);
1191
1192 helper.setObjectArrayElement(rttResults, i, rttResult);
1193 }
1194
1195 helper.reportEvent(mCls, "onRttResults", "(I[Landroid/net/wifi/RttManager$RttResult;)V",
1196 id, rttResults.get());
1197 }
1198
1199 const int MaxRttConfigs = 16;
1200
android_net_wifi_requestRange(JNIEnv * env,jclass cls,jint iface,jint id,jobject params)1201 static jboolean android_net_wifi_requestRange(
1202 JNIEnv *env, jclass cls, jint iface, jint id, jobject params) {
1203
1204 JNIHelper helper(env);
1205
1206 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1207 ALOGD("sending rtt request [%d] = %p", id, handle);
1208 if (params == NULL) {
1209 ALOGE("ranging params are empty");
1210 return false;
1211 }
1212
1213 wifi_rtt_config configs[MaxRttConfigs];
1214 memset(&configs, 0, sizeof(configs));
1215
1216 int len = helper.getArrayLength((jobjectArray)params);
1217 if (len > MaxRttConfigs) {
1218 return false;
1219 }
1220
1221 for (int i = 0; i < len; i++) {
1222
1223 JNIObject<jobject> param = helper.getObjectArrayElement((jobjectArray)params, i);
1224 if (param == NULL) {
1225 ALOGD("could not get element %d", i);
1226 continue;
1227 }
1228
1229 wifi_rtt_config &config = configs[i];
1230
1231 parseMacAddress(env, param, config.addr);
1232 config.type = (wifi_rtt_type)helper.getIntField(param, "requestType");
1233 config.peer = (rtt_peer_type)helper.getIntField(param, "deviceType");
1234 config.channel.center_freq = helper.getIntField(param, "frequency");
1235 config.channel.width = (wifi_channel_width) helper.getIntField(param, "channelWidth");
1236 config.channel.center_freq0 = helper.getIntField(param, "centerFreq0");
1237 config.channel.center_freq1 = helper.getIntField(param, "centerFreq1");
1238
1239 config.num_burst = helper.getIntField(param, "numberBurst");
1240 config.burst_period = (unsigned) helper.getIntField(param, "interval");
1241 config.num_frames_per_burst = (unsigned) helper.getIntField(param, "numSamplesPerBurst");
1242 config.num_retries_per_rtt_frame = (unsigned) helper.getIntField(param,
1243 "numRetriesPerMeasurementFrame");
1244 config.num_retries_per_ftmr = (unsigned) helper.getIntField(param, "numRetriesPerFTMR");
1245 config.LCI_request = helper.getBoolField(param, "LCIRequest") ? 1 : 0;
1246 config.LCR_request = helper.getBoolField(param, "LCRRequest") ? 1 : 0;
1247 config.burst_duration = (unsigned) helper.getIntField(param, "burstTimeout");
1248 config.preamble = (wifi_rtt_preamble) helper.getIntField(param, "preamble");
1249 config.bw = (wifi_rtt_bw) helper.getIntField(param, "bandwidth");
1250
1251 ALOGD("RTT request destination %d: type is %d, peer is %d, bw is %d, center_freq is %d ", i,
1252 config.type,config.peer, config.channel.width, config.channel.center_freq);
1253 ALOGD("center_freq0 is %d, center_freq1 is %d, num_burst is %d,interval is %d",
1254 config.channel.center_freq0, config.channel.center_freq1, config.num_burst,
1255 config.burst_period);
1256 ALOGD("frames_per_burst is %d, retries of measurement frame is %d, retries_per_ftmr is %d",
1257 config.num_frames_per_burst, config.num_retries_per_rtt_frame,
1258 config.num_retries_per_ftmr);
1259 ALOGD("LCI_requestis %d, LCR_request is %d, burst_timeout is %d, preamble is %d, bw is %d",
1260 config.LCI_request, config.LCR_request, config.burst_duration, config.preamble,
1261 config.bw);
1262 }
1263
1264 wifi_rtt_event_handler handler;
1265 handler.on_rtt_results = &onRttResults;
1266
1267 return hal_fn.wifi_rtt_range_request(id, handle, len, configs, handler) == WIFI_SUCCESS;
1268 }
1269
android_net_wifi_cancelRange(JNIEnv * env,jclass cls,jint iface,jint id,jobject params)1270 static jboolean android_net_wifi_cancelRange(
1271 JNIEnv *env, jclass cls, jint iface, jint id, jobject params) {
1272
1273 JNIHelper helper(env);
1274 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1275 ALOGD("cancelling rtt request [%d] = %p", id, handle);
1276
1277 if (params == NULL) {
1278 ALOGE("ranging params are empty");
1279 return false;
1280 }
1281
1282 mac_addr addrs[MaxRttConfigs];
1283 memset(&addrs, 0, sizeof(addrs));
1284
1285 int len = helper.getArrayLength((jobjectArray)params);
1286 if (len > MaxRttConfigs) {
1287 return false;
1288 }
1289
1290 for (int i = 0; i < len; i++) {
1291
1292 JNIObject<jobject> param = helper.getObjectArrayElement(params, i);
1293 if (param == NULL) {
1294 ALOGD("could not get element %d", i);
1295 continue;
1296 }
1297
1298 parseMacAddress(env, param, addrs[i]);
1299 }
1300
1301 return hal_fn.wifi_rtt_range_cancel(id, handle, len, addrs) == WIFI_SUCCESS;
1302 }
1303
android_net_wifi_enableResponder(JNIEnv * env,jclass cls,jint iface,jint id,jint timeout_seconds,jobject channel_hint)1304 static jobject android_net_wifi_enableResponder(
1305 JNIEnv *env, jclass cls, jint iface, jint id, jint timeout_seconds, jobject channel_hint) {
1306 JNIHelper helper(env);
1307 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1308 if (DBG) ALOGD("enabling responder request [%d] = %p", id, handle);
1309 wifi_channel_info channel;
1310 // Get channel information from HAL if it's not provided by caller.
1311 if (channel_hint == NULL) {
1312 wifi_rtt_responder responder_info_hint;
1313 bool status = hal_fn.wifi_rtt_get_responder_info(handle, &responder_info_hint);
1314 if (status != WIFI_SUCCESS) {
1315 ALOGE("could not get available channel for responder");
1316 return NULL;
1317 }
1318 channel = responder_info_hint.channel;
1319 } else {
1320 channel.center_freq = helper.getIntField(channel_hint, "mPrimaryFrequency");
1321 channel.center_freq0 = helper.getIntField(channel_hint, "mCenterFrequency0");
1322 channel.center_freq1 = helper.getIntField(channel_hint, "mCenterFrequency1");
1323 channel.width = (wifi_channel_width)helper.getIntField(channel_hint, "mChannelWidth");
1324 }
1325
1326 if (DBG) {
1327 ALOGD("wifi_channel_width: %d, center_freq: %d, center_freq0: %d",
1328 channel.width, channel.center_freq, channel.center_freq0);
1329 }
1330
1331 wifi_rtt_responder responder_info_used;
1332 bool status = hal_fn.wifi_enable_responder(id, handle, channel, timeout_seconds,
1333 &responder_info_used);
1334 if (status != WIFI_SUCCESS) {
1335 ALOGE("enabling responder mode failed");
1336 return NULL;
1337 }
1338 wifi_channel_info channel_used = responder_info_used.channel;
1339 if (DBG) {
1340 ALOGD("wifi_channel_width: %d, center_freq: %d, center_freq0: %d",
1341 channel_used.width, channel_used.center_freq, channel_used.center_freq0);
1342 }
1343 JNIObject<jobject> responderConfig =
1344 helper.createObject("android/net/wifi/RttManager$ResponderConfig");
1345 if (responderConfig == NULL) return NULL;
1346 helper.setIntField(responderConfig, "frequency", channel_used.center_freq);
1347 helper.setIntField(responderConfig, "centerFreq0", channel_used.center_freq0);
1348 helper.setIntField(responderConfig, "centerFreq1", channel_used.center_freq1);
1349 helper.setIntField(responderConfig, "channelWidth", channel_used.width);
1350 helper.setIntField(responderConfig, "preamble", responder_info_used.preamble);
1351 return responderConfig.detach();
1352 }
1353
android_net_wifi_disableResponder(JNIEnv * env,jclass cls,jint iface,jint id)1354 static jboolean android_net_wifi_disableResponder(
1355 JNIEnv *env, jclass cls, jint iface, jint id) {
1356 JNIHelper helper(env);
1357 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1358 if (DBG) ALOGD("disabling responder request [%d] = %p", id, handle);
1359 return hal_fn.wifi_disable_responder(id, handle) == WIFI_SUCCESS;
1360 }
1361
1362
android_net_wifi_setScanningMacOui(JNIEnv * env,jclass cls,jint iface,jbyteArray param)1363 static jboolean android_net_wifi_setScanningMacOui(JNIEnv *env, jclass cls,
1364 jint iface, jbyteArray param) {
1365
1366 JNIHelper helper(env);
1367 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1368 ALOGD("setting scan oui %p", handle);
1369
1370 static const unsigned oui_len = 3; /* OUI is upper 3 bytes of mac_address */
1371 int len = helper.getArrayLength(param);
1372 if (len != oui_len) {
1373 ALOGE("invalid oui length %d", len);
1374 return false;
1375 }
1376
1377 ScopedBytesRW paramBytes(env, param);
1378 jbyte* bytes = paramBytes.get();
1379 if (bytes == NULL) {
1380 ALOGE("failed to get setScanningMacOui param array");
1381 return false;
1382 }
1383
1384 return hal_fn.wifi_set_scanning_mac_oui(handle, (byte *)bytes) == WIFI_SUCCESS;
1385 }
1386
android_net_wifi_is_get_channels_for_band_supported(JNIEnv * env,jclass cls)1387 static jboolean android_net_wifi_is_get_channels_for_band_supported(JNIEnv *env, jclass cls){
1388 return (hal_fn.wifi_get_valid_channels == wifi_get_valid_channels_stub);
1389 }
1390
android_net_wifi_getValidChannels(JNIEnv * env,jclass cls,jint iface,jint band)1391 static jintArray android_net_wifi_getValidChannels(JNIEnv *env, jclass cls,
1392 jint iface, jint band) {
1393
1394 JNIHelper helper(env);
1395 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1396 ALOGV("getting valid channels %p", handle);
1397
1398 static const int MaxChannels = 64;
1399 wifi_channel channels[64];
1400 int num_channels = 0;
1401 wifi_error result = hal_fn.wifi_get_valid_channels(handle, band, MaxChannels,
1402 channels, &num_channels);
1403
1404 if (result == WIFI_SUCCESS) {
1405 JNIObject<jintArray> channelArray = helper.newIntArray(num_channels);
1406 if (channelArray == NULL) {
1407 ALOGE("failed to allocate channel list, num_channels=%d", num_channels);
1408 return NULL;
1409 }
1410
1411 helper.setIntArrayRegion(channelArray, 0, num_channels, channels);
1412 return channelArray.detach();
1413 } else {
1414 ALOGE("failed to get channel list : %d", result);
1415 return NULL;
1416 }
1417 }
1418
android_net_wifi_setDfsFlag(JNIEnv * env,jclass cls,jint iface,jboolean dfs)1419 static jboolean android_net_wifi_setDfsFlag(JNIEnv *env, jclass cls, jint iface, jboolean dfs) {
1420
1421 JNIHelper helper(env);
1422 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1423 ALOGD("setting dfs flag to %s, %p", dfs ? "true" : "false", handle);
1424
1425 u32 nodfs = dfs ? 0 : 1;
1426 wifi_error result = hal_fn.wifi_set_nodfs_flag(handle, nodfs);
1427 return result == WIFI_SUCCESS;
1428 }
1429
android_net_wifi_get_rtt_capabilities(JNIEnv * env,jclass cls,jint iface)1430 static jobject android_net_wifi_get_rtt_capabilities(JNIEnv *env, jclass cls, jint iface) {
1431
1432 JNIHelper helper(env);
1433 wifi_rtt_capabilities rtt_capabilities;
1434 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1435 wifi_error ret = hal_fn.wifi_get_rtt_capabilities(handle, &rtt_capabilities);
1436
1437 if(WIFI_SUCCESS == ret) {
1438 JNIObject<jobject> capabilities = helper.createObject(
1439 "android/net/wifi/RttManager$RttCapabilities");
1440 helper.setBooleanField(capabilities, "oneSidedRttSupported",
1441 rtt_capabilities.rtt_one_sided_supported == 1);
1442 helper.setBooleanField(capabilities, "twoSided11McRttSupported",
1443 rtt_capabilities.rtt_ftm_supported == 1);
1444 helper.setBooleanField(capabilities, "lciSupported",
1445 rtt_capabilities.lci_support);
1446 helper.setBooleanField(capabilities, "lcrSupported",
1447 rtt_capabilities.lcr_support);
1448 helper.setIntField(capabilities, "preambleSupported",
1449 rtt_capabilities.preamble_support);
1450 helper.setIntField(capabilities, "bwSupported",
1451 rtt_capabilities.bw_support);
1452 helper.setBooleanField(capabilities, "responderSupported",
1453 rtt_capabilities.responder_supported == 1);
1454 if (DBG) {
1455 ALOGD("One side RTT is %s", rtt_capabilities.rtt_one_sided_supported == 1 ?
1456 "supported" : "not supported");
1457 ALOGD("Two side RTT is %s", rtt_capabilities.rtt_ftm_supported == 1 ?
1458 "supported" : "not supported");
1459 ALOGD("LCR is %s", rtt_capabilities.lcr_support == 1 ? "supported" : "not supported");
1460 ALOGD("LCI is %s", rtt_capabilities.lci_support == 1 ? "supported" : "not supported");
1461 ALOGD("Supported preamble is %d", rtt_capabilities.preamble_support);
1462 ALOGD("Supported bandwidth is %d", rtt_capabilities.bw_support);
1463 ALOGD("Sta responder is %s",
1464 rtt_capabilities.responder_supported == 1 ? "supported" : "not supported");
1465 }
1466 return capabilities.detach();
1467 } else {
1468 return NULL;
1469 }
1470 }
1471
android_net_wifi_get_apf_capabilities(JNIEnv * env,jclass cls,jint iface)1472 static jobject android_net_wifi_get_apf_capabilities(JNIEnv *env, jclass cls,
1473 jint iface) {
1474
1475 JNIHelper helper(env);
1476 u32 version = 0, max_len = 0;
1477 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1478 wifi_error ret = hal_fn.wifi_get_packet_filter_capabilities(handle, &version, &max_len);
1479
1480 if (WIFI_SUCCESS == ret) {
1481 // Cannot just use createObject() because members are final and initializer values must be
1482 // passed via ApfCapabilities().
1483 JNIObject<jclass> apf_cls(helper, env->FindClass("android/net/apf/ApfCapabilities"));
1484 if (apf_cls == NULL) {
1485 ALOGE("Error in finding class android/net/apf/ApfCapabilities");
1486 return NULL;
1487 }
1488 jmethodID constructor = env->GetMethodID(apf_cls, "<init>", "(III)V");
1489 if (constructor == 0) {
1490 ALOGE("Error in constructor ID for android/net/apf/ApfCapabilities");
1491 return NULL;
1492 }
1493 JNIObject<jobject> capabilities(helper, env->NewObject(apf_cls, constructor, version,
1494 max_len, ARPHRD_ETHER));
1495 if (capabilities == NULL) {
1496 ALOGE("Could not create new object of android/net/apf/ApfCapabilities");
1497 return NULL;
1498 }
1499 ALOGD("APF version supported: %d", version);
1500 ALOGD("Maximum APF program size: %d", max_len);
1501 return capabilities.detach();
1502 } else {
1503 return NULL;
1504 }
1505 }
1506
android_net_wifi_install_packet_filter(JNIEnv * env,jclass cls,jint iface,jbyteArray jfilter)1507 static jboolean android_net_wifi_install_packet_filter(JNIEnv *env, jclass cls, jint iface,
1508 jbyteArray jfilter) {
1509
1510 JNIHelper helper(env);
1511 const u8* filter = (uint8_t*)env->GetByteArrayElements(jfilter, NULL);
1512 const u32 filter_len = env->GetArrayLength(jfilter);
1513 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1514 wifi_error ret = hal_fn.wifi_set_packet_filter(handle, filter, filter_len);
1515 env->ReleaseByteArrayElements(jfilter, (jbyte*)filter, JNI_ABORT);
1516 return WIFI_SUCCESS == ret;
1517 }
1518
android_net_wifi_set_Country_Code_Hal(JNIEnv * env,jclass cls,jint iface,jstring country_code)1519 static jboolean android_net_wifi_set_Country_Code_Hal(JNIEnv *env,jclass cls, jint iface,
1520 jstring country_code) {
1521
1522 JNIHelper helper(env);
1523 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1524
1525 ScopedUtfChars chars(env, country_code);
1526 const char *country = chars.c_str();
1527
1528 ALOGD("set country code: %s", country);
1529 wifi_error res = hal_fn.wifi_set_country_code(handle, country);
1530 return res == WIFI_SUCCESS;
1531 }
1532
android_net_wifi_enable_disable_tdls(JNIEnv * env,jclass cls,jint iface,jboolean enable,jstring addr)1533 static jboolean android_net_wifi_enable_disable_tdls(JNIEnv *env,jclass cls, jint iface,
1534 jboolean enable, jstring addr) {
1535
1536 JNIHelper helper(env);
1537 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1538
1539 mac_addr address;
1540 parseMacAddress(env, addr, address);
1541 wifi_tdls_handler tdls_handler;
1542 //tdls_handler.on_tdls_state_changed = &on_tdls_state_changed;
1543
1544 if(enable) {
1545 return (hal_fn.wifi_enable_tdls(handle, address, NULL, tdls_handler) == WIFI_SUCCESS);
1546 } else {
1547 return (hal_fn.wifi_disable_tdls(handle, address) == WIFI_SUCCESS);
1548 }
1549 }
1550
on_tdls_state_changed(mac_addr addr,wifi_tdls_status status)1551 static void on_tdls_state_changed(mac_addr addr, wifi_tdls_status status) {
1552
1553 JNIHelper helper(mVM);
1554
1555 ALOGD("on_tdls_state_changed is called: vm = %p, obj = %p", mVM, mCls);
1556
1557 char mac[32];
1558 sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4],
1559 addr[5]);
1560
1561 JNIObject<jstring> mac_address = helper.newStringUTF(mac);
1562 helper.reportEvent(mCls, "onTdlsStatus", "(Ljava/lang/StringII;)V",
1563 mac_address.get(), status.state, status.reason);
1564
1565 }
1566
android_net_wifi_get_tdls_status(JNIEnv * env,jclass cls,jint iface,jstring addr)1567 static jobject android_net_wifi_get_tdls_status(JNIEnv *env,jclass cls, jint iface,jstring addr) {
1568
1569 JNIHelper helper(env);
1570 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1571
1572 mac_addr address;
1573 parseMacAddress(env, addr, address);
1574
1575 wifi_tdls_status status;
1576
1577 wifi_error ret;
1578 ret = hal_fn.wifi_get_tdls_status(handle, address, &status );
1579
1580 if (ret != WIFI_SUCCESS) {
1581 return NULL;
1582 } else {
1583 JNIObject<jobject> tdls_status = helper.createObject(
1584 "com/android/server/wifi/WifiNative$TdlsStatus");
1585 helper.setIntField(tdls_status, "channel", status.channel);
1586 helper.setIntField(tdls_status, "global_operating_class", status.global_operating_class);
1587 helper.setIntField(tdls_status, "state", status.state);
1588 helper.setIntField(tdls_status, "reason", status.reason);
1589 return tdls_status.detach();
1590 }
1591 }
1592
android_net_wifi_get_tdls_capabilities(JNIEnv * env,jclass cls,jint iface)1593 static jobject android_net_wifi_get_tdls_capabilities(JNIEnv *env, jclass cls, jint iface) {
1594
1595 JNIHelper helper(env);
1596 wifi_tdls_capabilities tdls_capabilities;
1597 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1598 wifi_error ret = hal_fn.wifi_get_tdls_capabilities(handle, &tdls_capabilities);
1599
1600 if (WIFI_SUCCESS == ret) {
1601 JNIObject<jobject> capabilities = helper.createObject(
1602 "com/android/server/wifi/WifiNative$TdlsCapabilities");
1603 helper.setIntField(capabilities, "maxConcurrentTdlsSessionNumber",
1604 tdls_capabilities.max_concurrent_tdls_session_num);
1605 helper.setBooleanField(capabilities, "isGlobalTdlsSupported",
1606 tdls_capabilities.is_global_tdls_supported == 1);
1607 helper.setBooleanField(capabilities, "isPerMacTdlsSupported",
1608 tdls_capabilities.is_per_mac_tdls_supported == 1);
1609 helper.setBooleanField(capabilities, "isOffChannelTdlsSupported",
1610 tdls_capabilities.is_off_channel_tdls_supported);
1611
1612 ALOGD("TDLS Max Concurrent Tdls Session Number is: %d",
1613 tdls_capabilities.max_concurrent_tdls_session_num);
1614 ALOGD("Global Tdls is: %s", tdls_capabilities.is_global_tdls_supported == 1 ? "support" :
1615 "not support");
1616 ALOGD("Per Mac Tdls is: %s", tdls_capabilities.is_per_mac_tdls_supported == 1 ? "support" :
1617 "not support");
1618 ALOGD("Off Channel Tdls is: %s", tdls_capabilities.is_off_channel_tdls_supported == 1 ?
1619 "support" : "not support");
1620
1621 return capabilities.detach();
1622 } else {
1623 return NULL;
1624 }
1625 }
1626
1627 // ----------------------------------------------------------------------------
1628 // Debug framework
1629 // ----------------------------------------------------------------------------
android_net_wifi_get_supported_logger_feature(JNIEnv * env,jclass cls,jint iface)1630 static jint android_net_wifi_get_supported_logger_feature(JNIEnv *env, jclass cls, jint iface){
1631 //Not implemented yet
1632 return -1;
1633 }
1634
android_net_wifi_get_driver_version(JNIEnv * env,jclass cls,jint iface)1635 static jobject android_net_wifi_get_driver_version(JNIEnv *env, jclass cls, jint iface) {
1636 //Need to be fixed. The memory should be allocated from lower layer
1637 //char *buffer = NULL;
1638 JNIHelper helper(env);
1639 int buffer_length = 256;
1640 char *buffer = (char *)malloc(buffer_length);
1641 if (!buffer) return NULL;
1642 memset(buffer, 0, buffer_length);
1643 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1644
1645 ALOGD("android_net_wifi_get_driver_version = %p", handle);
1646
1647 if (handle == 0) {
1648 free(buffer);
1649 return NULL;
1650 }
1651
1652 wifi_error result = hal_fn.wifi_get_driver_version(handle, buffer, buffer_length);
1653
1654 if (result == WIFI_SUCCESS) {
1655 ALOGD("buffer is %p, length is %d", buffer, buffer_length);
1656 JNIObject<jstring> driver_version = helper.newStringUTF(buffer);
1657 free(buffer);
1658 return driver_version.detach();
1659 } else {
1660 ALOGE("Fail to get driver version");
1661 free(buffer);
1662 return NULL;
1663 }
1664 }
1665
android_net_wifi_get_firmware_version(JNIEnv * env,jclass cls,jint iface)1666 static jobject android_net_wifi_get_firmware_version(JNIEnv *env, jclass cls, jint iface) {
1667
1668 //char *buffer = NULL;
1669 JNIHelper helper(env);
1670 int buffer_length = 256;
1671 char *buffer = (char *)malloc(buffer_length);
1672 if (!buffer) return NULL;
1673 memset(buffer, 0, buffer_length);
1674 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1675
1676 ALOGD("android_net_wifi_get_firmware_version = %p", handle);
1677
1678 if (handle == 0) {
1679 free(buffer);
1680 return NULL;
1681 }
1682
1683 wifi_error result = hal_fn.wifi_get_firmware_version(handle, buffer, buffer_length);
1684
1685 if (result == WIFI_SUCCESS) {
1686 ALOGD("buffer is %p, length is %d", buffer, buffer_length);
1687 JNIObject<jstring> firmware_version = helper.newStringUTF(buffer);
1688 free(buffer);
1689 return firmware_version.detach();
1690 } else {
1691 ALOGE("Fail to get Firmware version");
1692 free(buffer);
1693 return NULL;
1694 }
1695 }
1696
android_net_wifi_get_ring_buffer_status(JNIEnv * env,jclass cls,jint iface)1697 static jobject android_net_wifi_get_ring_buffer_status (JNIEnv *env, jclass cls, jint iface) {
1698
1699 JNIHelper helper(env);
1700 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1701
1702 ALOGD("android_net_wifi_get_ring_buffer_status = %p", handle);
1703
1704 if (handle == 0) {
1705 return NULL;
1706 }
1707
1708 //wifi_ring_buffer_status *status = NULL;
1709 u32 num_rings = 10;
1710 wifi_ring_buffer_status *status =
1711 (wifi_ring_buffer_status *)malloc(sizeof(wifi_ring_buffer_status) * num_rings);
1712 if (!status) return NULL;
1713 memset(status, 0, sizeof(wifi_ring_buffer_status) * num_rings);
1714 wifi_error result = hal_fn.wifi_get_ring_buffers_status(handle, &num_rings, status);
1715 if (result == WIFI_SUCCESS) {
1716 ALOGD("status is %p, number is %d", status, num_rings);
1717
1718 JNIObject<jobjectArray> ringBuffersStatus = helper.newObjectArray(
1719 num_rings, "com/android/server/wifi/WifiNative$RingBufferStatus", NULL);
1720
1721 wifi_ring_buffer_status *tmp = status;
1722
1723 for(u32 i = 0; i < num_rings; i++, tmp++) {
1724
1725 JNIObject<jobject> ringStatus = helper.createObject(
1726 "com/android/server/wifi/WifiNative$RingBufferStatus");
1727
1728 if (ringStatus == NULL) {
1729 ALOGE("Error in creating ringBufferStatus");
1730 free(status);
1731 return NULL;
1732 }
1733
1734 char name[32];
1735 for(int j = 0; j < 32; j++) {
1736 name[j] = tmp->name[j];
1737 }
1738
1739 helper.setStringField(ringStatus, "name", name);
1740 helper.setIntField(ringStatus, "flag", tmp->flags);
1741 helper.setIntField(ringStatus, "ringBufferId", tmp->ring_id);
1742 helper.setIntField(ringStatus, "ringBufferByteSize", tmp->ring_buffer_byte_size);
1743 helper.setIntField(ringStatus, "verboseLevel", tmp->verbose_level);
1744 helper.setIntField(ringStatus, "writtenBytes", tmp->written_bytes);
1745 helper.setIntField(ringStatus, "readBytes", tmp->read_bytes);
1746 helper.setIntField(ringStatus, "writtenRecords", tmp->written_records);
1747
1748 helper.setObjectArrayElement(ringBuffersStatus, i, ringStatus);
1749 }
1750
1751 free(status);
1752 return ringBuffersStatus.detach();
1753 } else {
1754 free(status);
1755 return NULL;
1756 }
1757 }
1758
on_ring_buffer_data(char * ring_name,char * buffer,int buffer_size,wifi_ring_buffer_status * status)1759 static void on_ring_buffer_data(char *ring_name, char *buffer, int buffer_size,
1760 wifi_ring_buffer_status *status) {
1761
1762 if (!ring_name || !buffer || !status ||
1763 (unsigned int)buffer_size <= sizeof(wifi_ring_buffer_entry)) {
1764 ALOGE("Error input for on_ring_buffer_data!");
1765 return;
1766 }
1767
1768
1769 JNIHelper helper(mVM);
1770 /* ALOGD("on_ring_buffer_data called, vm = %p, obj = %p, env = %p buffer size = %d", mVM,
1771 mCls, env, buffer_size); */
1772
1773 JNIObject<jobject> ringStatus = helper.createObject(
1774 "com/android/server/wifi/WifiNative$RingBufferStatus");
1775 if (status == NULL) {
1776 ALOGE("Error in creating ringBufferStatus");
1777 return;
1778 }
1779
1780 helper.setStringField(ringStatus, "name", ring_name);
1781 helper.setIntField(ringStatus, "flag", status->flags);
1782 helper.setIntField(ringStatus, "ringBufferId", status->ring_id);
1783 helper.setIntField(ringStatus, "ringBufferByteSize", status->ring_buffer_byte_size);
1784 helper.setIntField(ringStatus, "verboseLevel", status->verbose_level);
1785 helper.setIntField(ringStatus, "writtenBytes", status->written_bytes);
1786 helper.setIntField(ringStatus, "readBytes", status->read_bytes);
1787 helper.setIntField(ringStatus, "writtenRecords", status->written_records);
1788
1789 JNIObject<jbyteArray> bytes = helper.newByteArray(buffer_size);
1790 helper.setByteArrayRegion(bytes, 0, buffer_size, (jbyte*)buffer);
1791
1792 helper.reportEvent(mCls,"onRingBufferData",
1793 "(Lcom/android/server/wifi/WifiNative$RingBufferStatus;[B)V",
1794 ringStatus.get(), bytes.get());
1795 }
1796
on_alert_data(wifi_request_id id,char * buffer,int buffer_size,int err_code)1797 static void on_alert_data(wifi_request_id id, char *buffer, int buffer_size, int err_code){
1798
1799 JNIHelper helper(mVM);
1800 ALOGD("on_alert_data called, vm = %p, obj = %p, buffer_size = %d, error code = %d"
1801 , mVM, mCls, buffer_size, err_code);
1802
1803 if (buffer_size > 0) {
1804 JNIObject<jbyteArray> records = helper.newByteArray(buffer_size);
1805 jbyte *bytes = (jbyte *) buffer;
1806 helper.setByteArrayRegion(records, 0,buffer_size, bytes);
1807 helper.reportEvent(mCls,"onWifiAlert","([BI)V", records.get(), err_code);
1808 } else {
1809 helper.reportEvent(mCls,"onWifiAlert","([BI)V", NULL, err_code);
1810 }
1811 }
1812
1813
android_net_wifi_start_logging_ring_buffer(JNIEnv * env,jclass cls,jint iface,jint verbose_level,jint flags,jint max_interval,jint min_data_size,jstring ring_name)1814 static jboolean android_net_wifi_start_logging_ring_buffer(JNIEnv *env, jclass cls, jint iface,
1815 jint verbose_level,jint flags, jint max_interval,jint min_data_size, jstring ring_name) {
1816
1817 JNIHelper helper(env);
1818 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1819
1820 ALOGD("android_net_wifi_start_logging_ring_buffer = %p", handle);
1821
1822 if (handle == 0) {
1823 return false;
1824 }
1825
1826 ScopedUtfChars chars(env, ring_name);
1827 const char* ring_name_const_char = chars.c_str();
1828 int ret = hal_fn.wifi_start_logging(handle, verbose_level,
1829 flags, max_interval, min_data_size, const_cast<char *>(ring_name_const_char));
1830
1831 if (ret != WIFI_SUCCESS) {
1832 ALOGE("Fail to start logging for ring %s", ring_name_const_char);
1833 } else {
1834 ALOGD("start logging for ring %s", ring_name_const_char);
1835 }
1836
1837 return ret == WIFI_SUCCESS;
1838 }
1839
android_net_wifi_get_ring_buffer_data(JNIEnv * env,jclass cls,jint iface,jstring ring_name)1840 static jboolean android_net_wifi_get_ring_buffer_data(JNIEnv *env, jclass cls, jint iface,
1841 jstring ring_name) {
1842
1843 JNIHelper helper(env);
1844 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1845 // ALOGD("android_net_wifi_get_ring_buffer_data = %p", handle);
1846
1847 ScopedUtfChars chars(env, ring_name);
1848 const char* ring_name_const_char = chars.c_str();
1849 int result = hal_fn.wifi_get_ring_data(handle, const_cast<char *>(ring_name_const_char));
1850 return result == WIFI_SUCCESS;
1851 }
1852
1853
on_firmware_memory_dump(char * buffer,int buffer_size)1854 static void on_firmware_memory_dump(char *buffer, int buffer_size) {
1855
1856 JNIHelper helper(mVM);
1857 /* ALOGD("on_firmware_memory_dump called, vm = %p, obj = %p, env = %p buffer_size = %d"
1858 , mVM, mCls, env, buffer_size); */
1859
1860 if (buffer_size > 0) {
1861 JNIObject<jbyteArray> dump = helper.newByteArray(buffer_size);
1862 jbyte *bytes = (jbyte *) (buffer);
1863 helper.setByteArrayRegion(dump, 0, buffer_size, bytes);
1864 helper.reportEvent(mCls,"onWifiFwMemoryAvailable","([B)V", dump.get());
1865 }
1866 }
1867
android_net_wifi_get_fw_memory_dump(JNIEnv * env,jclass cls,jint iface)1868 static jboolean android_net_wifi_get_fw_memory_dump(JNIEnv *env, jclass cls, jint iface){
1869
1870 JNIHelper helper(env);
1871 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1872 // ALOGD("android_net_wifi_get_fw_memory_dump = %p", handle);
1873
1874 if (handle == NULL) {
1875 ALOGE("Can not get wifi_interface_handle");
1876 return false;
1877 }
1878
1879 wifi_firmware_memory_dump_handler fw_dump_handle;
1880 fw_dump_handle.on_firmware_memory_dump = on_firmware_memory_dump;
1881 int result = hal_fn.wifi_get_firmware_memory_dump(handle, fw_dump_handle);
1882 return result == WIFI_SUCCESS;
1883
1884 }
1885
1886 std::vector<jbyte>* driver_state_dump_buffer_for_callback = nullptr;
1887
1888 static void on_driver_state_dump(char *buffer, int buffer_size);
1889 static wifi_driver_memory_dump_callbacks driver_state_dump_callbacks = {
1890 on_driver_state_dump
1891 };
1892
on_driver_state_dump(char * buffer,int buffer_size)1893 static void on_driver_state_dump(char *buffer, int buffer_size) {
1894
1895 if (!driver_state_dump_buffer_for_callback) {
1896 ALOGE("Unexpected call from HAL implementation, into %s", __func__);
1897 return;
1898 }
1899
1900 if (buffer_size > 0) {
1901 driver_state_dump_buffer_for_callback->insert(
1902 driver_state_dump_buffer_for_callback->end(), buffer, buffer + buffer_size);
1903 }
1904 }
1905
1906 // TODO(quiche): Add unit tests. b/28072392
android_net_wifi_get_driver_state_dump(JNIEnv * env,jclass cls,jint iface)1907 static jbyteArray android_net_wifi_get_driver_state_dump(JNIEnv *env, jclass cls, jint iface){
1908
1909 JNIHelper helper(env);
1910 wifi_interface_handle interface_handle = getIfaceHandle(helper, cls, iface);
1911
1912 if (!interface_handle) {
1913 return nullptr;
1914 }
1915
1916 int result;
1917 std::vector<jbyte> state_dump_buffer_local;
1918 driver_state_dump_buffer_for_callback = &state_dump_buffer_local;
1919 result = hal_fn.wifi_get_driver_memory_dump(interface_handle, driver_state_dump_callbacks);
1920 driver_state_dump_buffer_for_callback = nullptr;
1921
1922 if (result != WIFI_SUCCESS) {
1923 ALOGW("HAL's wifi_get_driver_memory_dump returned %d", result);
1924 return nullptr;
1925 }
1926
1927 if (state_dump_buffer_local.empty()) {
1928 ALOGW("HAL's wifi_get_driver_memory_dump provided zero bytes");
1929 return nullptr;
1930 }
1931
1932 const size_t dump_size = state_dump_buffer_local.size();
1933 JNIObject<jbyteArray> driver_dump_java = helper.newByteArray(dump_size);
1934 if (!driver_dump_java) {
1935 ALOGW("Failed to allocate Java buffer for driver state dump");
1936 return nullptr;
1937 }
1938
1939 helper.setByteArrayRegion(driver_dump_java, 0, dump_size, state_dump_buffer_local.data());
1940 return driver_dump_java.detach();
1941 }
1942
android_net_wifi_set_log_handler(JNIEnv * env,jclass cls,jint iface,jint id)1943 static jboolean android_net_wifi_set_log_handler(JNIEnv *env, jclass cls, jint iface, jint id) {
1944
1945 JNIHelper helper(env);
1946 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1947 ALOGD("android_net_wifi_set_log_handler = %p", handle);
1948
1949 //initialize the handler on first time
1950 wifi_ring_buffer_data_handler handler;
1951 handler.on_ring_buffer_data = &on_ring_buffer_data;
1952 int result = hal_fn.wifi_set_log_handler(id, handle, handler);
1953 if (result != WIFI_SUCCESS) {
1954 ALOGE("Fail to set logging handler");
1955 return false;
1956 }
1957
1958 //set alter handler This will start alert too
1959 wifi_alert_handler alert_handler;
1960 alert_handler.on_alert = &on_alert_data;
1961 result = hal_fn.wifi_set_alert_handler(id, handle, alert_handler);
1962 if (result != WIFI_SUCCESS) {
1963 ALOGE(" Fail to set alert handler");
1964 return false;
1965 }
1966
1967 return true;
1968 }
1969
android_net_wifi_reset_log_handler(JNIEnv * env,jclass cls,jint iface,jint id)1970 static jboolean android_net_wifi_reset_log_handler(JNIEnv *env, jclass cls, jint iface, jint id) {
1971
1972 JNIHelper helper(env);
1973 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
1974
1975 //reset alter handler
1976 ALOGD("android_net_wifi_reset_alert_handler = %p", handle);
1977 int result = hal_fn.wifi_reset_alert_handler(id, handle);
1978 if (result != WIFI_SUCCESS) {
1979 ALOGE(" Fail to reset alert handler");
1980 return false;
1981 }
1982
1983 //reset log handler
1984 ALOGD("android_net_wifi_reset_log_handler = %p", handle);
1985 result = hal_fn.wifi_reset_log_handler(id, handle);
1986 if (result != WIFI_SUCCESS) {
1987 ALOGE("Fail to reset logging handler");
1988 return false;
1989 }
1990
1991 return true;
1992 }
1993
android_net_wifi_start_pkt_fate_monitoring(JNIEnv * env,jclass cls,jint iface)1994 static jint android_net_wifi_start_pkt_fate_monitoring(JNIEnv *env, jclass cls, jint iface) {
1995
1996 JNIHelper helper(env);
1997 return hal_fn.wifi_start_pkt_fate_monitoring(
1998 getIfaceHandle(helper, cls, iface));
1999 }
2000
2001 // Helper for make_default_fate().
set_to_max(T * value)2002 template<typename T> void set_to_max(T* value) {
2003 if (!value) {
2004 return;
2005 }
2006 *value = std::numeric_limits<T>::max();
2007 }
2008
2009 // make_default_fate() has two purposes:
2010 // 1) Minimize the chances of data leakage. In case the HAL gives us an overlong long |frame_len|,
2011 // for example, we want to return zeros, rather than other data from this process.
2012 // 2) Make it obvious when the HAL doesn't set a field. We accomplish this by setting fields
2013 // to "impossible" values, where possible.
2014 // Normally, such work would be done in a ctor. However, doing so would make the HAL API
2015 // incompatible with C. So we use a free-standing function instead.
2016 //
2017 // TODO(quiche): Add unit test for this function. b/27726696
make_default_fate()2018 template<typename FateReportT> FateReportT make_default_fate() {
2019
2020 FateReportT fate_report;
2021 set_to_max(&fate_report.fate);
2022 std::fill(std::begin(fate_report.md5_prefix), std::end(fate_report.md5_prefix), 0);
2023 set_to_max(&fate_report.frame_inf.payload_type);
2024 fate_report.frame_inf.frame_len = 0;
2025 fate_report.frame_inf.driver_timestamp_usec = 0;
2026 fate_report.frame_inf.firmware_timestamp_usec = 0;
2027 std::fill(std::begin(fate_report.frame_inf.frame_content.ieee_80211_mgmt_bytes),
2028 std::end(fate_report.frame_inf.frame_content.ieee_80211_mgmt_bytes), 0);
2029 return fate_report;
2030 }
2031
2032 // TODO(quiche): Add unit test for this function. b/27726696
get_pkt_fates(HalFateFetcherT fate_fetcher_func,const char * java_fate_type,JNIEnv * env,jclass cls,jint iface,jobjectArray reports)2033 template<typename FateReportT, typename HalFateFetcherT> wifi_error get_pkt_fates(
2034 HalFateFetcherT fate_fetcher_func, const char *java_fate_type,
2035 JNIEnv *env, jclass cls, jint iface, jobjectArray reports) {
2036
2037 JNIHelper helper(env);
2038 const size_t n_reports_wanted =
2039 std::min(helper.getArrayLength(reports), MAX_FATE_LOG_LEN);
2040
2041 std::vector<FateReportT> report_bufs(n_reports_wanted, make_default_fate<FateReportT>());
2042 size_t n_reports_provided = 0;
2043 wifi_error result = fate_fetcher_func(
2044 getIfaceHandle(helper, cls, iface),
2045 report_bufs.data(),
2046 n_reports_wanted,
2047 &n_reports_provided);
2048 if (result != WIFI_SUCCESS) {
2049 return result;
2050 }
2051
2052 if (n_reports_provided > n_reports_wanted) {
2053 LOG_ALWAYS_FATAL(
2054 "HAL data exceeds request; memory may be corrupt (provided: %zu, requested: %zu)",
2055 n_reports_provided, n_reports_wanted);
2056 }
2057
2058 for (size_t i = 0; i < n_reports_provided; ++i) {
2059 const FateReportT& report(report_bufs[i]);
2060
2061 const char *frame_bytes_native = nullptr;
2062 size_t max_frame_len;
2063 switch (report.frame_inf.payload_type) {
2064 case FRAME_TYPE_UNKNOWN:
2065 case FRAME_TYPE_ETHERNET_II:
2066 max_frame_len = MAX_FRAME_LEN_ETHERNET;
2067 frame_bytes_native = report.frame_inf.frame_content.ethernet_ii_bytes;
2068 break;
2069 case FRAME_TYPE_80211_MGMT:
2070 max_frame_len = MAX_FRAME_LEN_80211_MGMT;
2071 frame_bytes_native = report.frame_inf.frame_content.ieee_80211_mgmt_bytes;
2072 break;
2073 default:
2074 max_frame_len = 0;
2075 frame_bytes_native = 0;
2076 }
2077
2078 size_t copy_len = report.frame_inf.frame_len;
2079 if (copy_len > max_frame_len) {
2080 ALOGW("Overly long frame (len: %zu, max: %zu)", copy_len, max_frame_len);
2081 copy_len = max_frame_len;
2082 }
2083
2084 JNIObject<jbyteArray> frame_bytes_java = helper.newByteArray(copy_len);
2085 if (frame_bytes_java.isNull()) {
2086 ALOGE("Failed to allocate frame data buffer");
2087 return WIFI_ERROR_OUT_OF_MEMORY;
2088 }
2089 helper.setByteArrayRegion(frame_bytes_java, 0, copy_len,
2090 reinterpret_cast<const jbyte *>(frame_bytes_native));
2091
2092 JNIObject<jobject> fate_report = helper.createObjectWithArgs(
2093 java_fate_type,
2094 "(BJB[B)V", // byte, long, byte, byte array
2095 static_cast<jbyte>(report.fate),
2096 static_cast<jlong>(report.frame_inf.driver_timestamp_usec),
2097 static_cast<jbyte>(report.frame_inf.payload_type),
2098 frame_bytes_java.get());
2099 if (fate_report.isNull()) {
2100 ALOGE("Failed to create %s", java_fate_type);
2101 return WIFI_ERROR_OUT_OF_MEMORY;
2102 }
2103 helper.setObjectArrayElement(reports, i, fate_report);
2104 }
2105
2106 return result;
2107 }
2108
android_net_wifi_get_tx_pkt_fates(JNIEnv * env,jclass cls,jint iface,jobjectArray reports)2109 static jint android_net_wifi_get_tx_pkt_fates(JNIEnv *env, jclass cls, jint iface,
2110 jobjectArray reports) {
2111
2112 return get_pkt_fates<wifi_tx_report>(
2113 hal_fn.wifi_get_tx_pkt_fates, "com/android/server/wifi/WifiNative$TxFateReport",
2114 env, cls, iface, reports);
2115 }
2116
android_net_wifi_get_rx_pkt_fates(JNIEnv * env,jclass cls,jint iface,jobjectArray reports)2117 static jint android_net_wifi_get_rx_pkt_fates(JNIEnv *env, jclass cls, jint iface,
2118 jobjectArray reports) {
2119
2120 return get_pkt_fates<wifi_rx_report>(
2121 hal_fn.wifi_get_rx_pkt_fates, "com/android/server/wifi/WifiNative$RxFateReport",
2122 env, cls, iface, reports);
2123 }
2124
2125 // ----------------------------------------------------------------------------
2126 // ePno framework
2127 // ----------------------------------------------------------------------------
2128
2129
onPnoNetworkFound(wifi_request_id id,unsigned num_results,wifi_scan_result * results)2130 static void onPnoNetworkFound(wifi_request_id id,
2131 unsigned num_results, wifi_scan_result *results) {
2132 JNIHelper helper(mVM);
2133 ALOGD("onPnoNetworkFound called, vm = %p, obj = %p, num_results %u", mVM, mCls, num_results);
2134
2135 if (results == NULL || num_results == 0) {
2136 ALOGE("onPnoNetworkFound: Error no results");
2137 return;
2138 }
2139
2140 JNIObject<jobjectArray> scanResults = helper.newObjectArray(num_results,
2141 "android/net/wifi/ScanResult", NULL);
2142 if (scanResults == NULL) {
2143 ALOGE("onpnoNetworkFound: Error in allocating scanResults array");
2144 return;
2145 }
2146
2147 JNIObject<jintArray> beaconCaps = helper.newIntArray(num_results);
2148 if (beaconCaps == NULL) {
2149 ALOGE("onpnoNetworkFound: Error in allocating beaconCaps array");
2150 return;
2151 }
2152
2153 for (unsigned i=0; i<num_results; i++) {
2154
2155 JNIObject<jobject> scanResult = createScanResult(helper, &results[i], true);
2156 if (scanResult == NULL) {
2157 ALOGE("Error in creating scan result");
2158 return;
2159 }
2160
2161 helper.setObjectArrayElement(scanResults, i, scanResult);
2162 helper.setIntArrayRegion(beaconCaps, i, 1, (jint *)&(results[i].capability));
2163
2164 if (DBG) {
2165 ALOGD("ScanResult: IE length %d, i %u, <%s> rssi=%d %02x:%02x:%02x:%02x:%02x:%02x",
2166 results->ie_length, i, results[i].ssid, results[i].rssi,
2167 results[i].bssid[0], results[i].bssid[1],results[i].bssid[2],
2168 results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]);
2169 }
2170 }
2171
2172 helper.reportEvent(mCls, "onPnoNetworkFound", "(I[Landroid/net/wifi/ScanResult;[I)V", id,
2173 scanResults.get(), beaconCaps.get());
2174 }
2175
android_net_wifi_setPnoListNative(JNIEnv * env,jclass cls,jint iface,jint id,jobject settings)2176 static jboolean android_net_wifi_setPnoListNative(
2177 JNIEnv *env, jclass cls, jint iface, jint id, jobject settings) {
2178
2179 JNIHelper helper(env);
2180 wifi_epno_handler handler;
2181 handler.on_network_found = &onPnoNetworkFound;
2182
2183 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
2184 ALOGD("configure ePno list request [%d] = %p", id, handle);
2185
2186 if (settings == NULL) {
2187 return false;
2188 }
2189
2190 JNIObject<jobjectArray> list = helper.getArrayField(settings, "networkList",
2191 "[Lcom/android/server/wifi/WifiNative$PnoNetwork;");
2192 if (list == NULL) {
2193 return false;
2194 }
2195
2196 size_t len = helper.getArrayLength(list);
2197 if (len > (size_t)MAX_EPNO_NETWORKS) {
2198 return false;
2199 }
2200
2201 wifi_epno_params params;
2202 memset(¶ms, 0, sizeof(params));
2203
2204 for (unsigned int i = 0; i < len; i++) {
2205
2206 JNIObject<jobject> pno_net = helper.getObjectArrayElement(list, i);
2207 if (pno_net == NULL) {
2208 ALOGE("setPnoListNative: could not get element %d", i);
2209 continue;
2210 }
2211
2212 JNIObject<jstring> sssid = helper.getStringField(pno_net, "ssid");
2213 if (sssid == NULL) {
2214 ALOGE("Error setPnoListNative: getting ssid field");
2215 return false;
2216 }
2217
2218 ScopedUtfChars chars(env, (jstring)sssid.get());
2219 const char *ssid = chars.c_str();
2220 if (ssid == NULL) {
2221 ALOGE("Error setPnoListNative: getting ssid");
2222 return false;
2223 }
2224 int ssid_len = strnlen((const char*)ssid, 33);
2225 if (ssid_len > 32) {
2226 ALOGE("Error setPnoListNative: long ssid %zu", strnlen((const char*)ssid, 256));
2227 return false;
2228 }
2229
2230 if (ssid_len > 1 && ssid[0] == '"' && ssid[ssid_len-1] == '"')
2231 {
2232 // strip leading and trailing '"'
2233 ssid++;
2234 ssid_len-=2;
2235 }
2236 if (ssid_len == 0) {
2237 ALOGE("Error setPnoListNative: zero length ssid, skip it");
2238 continue;
2239 }
2240 memcpy(params.networks[i].ssid, ssid, ssid_len);
2241
2242 params.networks[i].auth_bit_field = helper.getByteField(pno_net, "auth_bit_field");
2243 params.networks[i].flags = helper.getByteField(pno_net, "flags");
2244 ALOGD(" setPnoListNative: idx %u auth %x flags %x [%s]", i,
2245 params.networks[i].auth_bit_field, params.networks[i].flags,
2246 params.networks[i].ssid);
2247 }
2248 params.min5GHz_rssi = helper.getIntField(settings, "min5GHzRssi");
2249 params.min24GHz_rssi = helper.getIntField(settings, "min24GHzRssi");
2250 params.initial_score_max = helper.getIntField(settings, "initialScoreMax");
2251 params.current_connection_bonus = helper.getIntField(settings, "currentConnectionBonus");
2252 params.same_network_bonus = helper.getIntField(settings, "sameNetworkBonus");
2253 params.secure_bonus = helper.getIntField(settings, "secureBonus");
2254 params.band5GHz_bonus = helper.getIntField(settings, "band5GHzBonus");
2255 params.num_networks = len;
2256
2257 int result = hal_fn.wifi_set_epno_list(id, handle, ¶ms, handler);
2258 ALOGD(" setPnoListNative: result %d", result);
2259
2260 return result >= 0;
2261 }
2262
android_net_wifi_resetPnoListNative(JNIEnv * env,jclass cls,jint iface,jint id)2263 static jboolean android_net_wifi_resetPnoListNative(
2264 JNIEnv *env, jclass cls, jint iface, jint id) {
2265
2266 JNIHelper helper(env);
2267
2268 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
2269 ALOGD("reset ePno list request [%d] = %p", id, handle);
2270
2271 // stop pno
2272 int result = hal_fn.wifi_reset_epno_list(id, handle);
2273 ALOGD(" ressetPnoListNative: result = %d", result);
2274 return result >= 0;
2275 }
2276
android_net_wifi_setBssidBlacklist(JNIEnv * env,jclass cls,jint iface,jint id,jobject list)2277 static jboolean android_net_wifi_setBssidBlacklist(
2278 JNIEnv *env, jclass cls, jint iface, jint id, jobject list) {
2279
2280 JNIHelper helper(env);
2281 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
2282 ALOGD("configure BSSID black list request [%d] = %p", id, handle);
2283
2284 wifi_bssid_params params;
2285 memset(¶ms, 0, sizeof(params));
2286
2287 if (list != NULL) {
2288 size_t len = helper.getArrayLength((jobjectArray)list);
2289 if (len > (size_t)MAX_BLACKLIST_BSSID) {
2290 return false;
2291 }
2292 for (unsigned int i = 0; i < len; i++) {
2293
2294 JNIObject<jobject> jbssid = helper.getObjectArrayElement(list, i);
2295 if (jbssid == NULL) {
2296 ALOGE("configure BSSID blacklist: could not get element %d", i);
2297 continue;
2298 }
2299
2300 ScopedUtfChars chars(env, (jstring)jbssid.get());
2301 const char *bssid = chars.c_str();
2302 if (bssid == NULL) {
2303 ALOGE("Error getting bssid");
2304 return false;
2305 }
2306
2307 mac_addr addr;
2308 parseMacAddress(bssid, addr);
2309 memcpy(params.bssids[i], addr, sizeof(mac_addr));
2310
2311 char bssidOut[32];
2312 sprintf(bssidOut, "%0x:%0x:%0x:%0x:%0x:%0x", addr[0], addr[1],
2313 addr[2], addr[3], addr[4], addr[5]);
2314
2315 ALOGD("BSSID blacklist: added bssid %s", bssidOut);
2316
2317 params.num_bssid++;
2318 }
2319 }
2320
2321 ALOGD("Added %d bssids", params.num_bssid);
2322 return hal_fn.wifi_set_bssid_blacklist(id, handle, params) == WIFI_SUCCESS;
2323 }
2324
android_net_wifi_start_sending_offloaded_packet(JNIEnv * env,jclass cls,jint iface,jint idx,jbyteArray srcMac,jbyteArray dstMac,jbyteArray pkt,jint period)2325 static jint android_net_wifi_start_sending_offloaded_packet(JNIEnv *env, jclass cls, jint iface,
2326 jint idx, jbyteArray srcMac, jbyteArray dstMac, jbyteArray pkt, jint period) {
2327 JNIHelper helper(env);
2328 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
2329 ALOGD("Start packet offload [%d] = %p", idx, handle);
2330 wifi_error ret;
2331 wifi_request_id id = idx;
2332
2333 ScopedBytesRO pktBytes(env, pkt), srcMacBytes(env, srcMac), dstMacBytes(env, dstMac);
2334
2335 byte * pkt_data = (byte*) pktBytes.get();
2336 unsigned short pkt_len = env->GetArrayLength(pkt);
2337 byte* src_mac_addr = (byte*) srcMacBytes.get();
2338 byte* dst_mac_addr = (byte*) dstMacBytes.get();
2339 int i;
2340 char macAddr[32];
2341 sprintf(macAddr, "%0x:%0x:%0x:%0x:%0x:%0x", src_mac_addr[0], src_mac_addr[1],
2342 src_mac_addr[2], src_mac_addr[3], src_mac_addr[4], src_mac_addr[5]);
2343 ALOGD("src_mac_addr %s", macAddr);
2344 sprintf(macAddr, "%0x:%0x:%0x:%0x:%0x:%0x", dst_mac_addr[0], dst_mac_addr[1],
2345 dst_mac_addr[2], dst_mac_addr[3], dst_mac_addr[4], dst_mac_addr[5]);
2346 ALOGD("dst_mac_addr %s", macAddr);
2347 ALOGD("pkt_len %d\n", pkt_len);
2348 ALOGD("Pkt data : ");
2349 for(i = 0; i < pkt_len; i++) {
2350 ALOGD(" %x ", pkt_data[i]);
2351 }
2352 ALOGD("\n");
2353 ret = hal_fn.wifi_start_sending_offloaded_packet(id, handle, pkt_data, pkt_len,
2354 src_mac_addr, dst_mac_addr, period);
2355 ALOGD("ret= %d\n", ret);
2356 return ret;
2357 }
2358
android_net_wifi_stop_sending_offloaded_packet(JNIEnv * env,jclass cls,jint iface,jint idx)2359 static jint android_net_wifi_stop_sending_offloaded_packet(JNIEnv *env, jclass cls,
2360 jint iface, jint idx) {
2361 int ret;
2362 JNIHelper helper(env);
2363 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
2364 ALOGD("Stop packet offload [%d] = %p", idx, handle);
2365 ret = hal_fn.wifi_stop_sending_offloaded_packet(idx, handle);
2366 ALOGD("ret= %d\n", ret);
2367 return ret;
2368 }
2369
onRssiThresholdbreached(wifi_request_id id,u8 * cur_bssid,s8 cur_rssi)2370 static void onRssiThresholdbreached(wifi_request_id id, u8 *cur_bssid, s8 cur_rssi) {
2371
2372 ALOGD("RSSI threshold breached, cur RSSI - %d!!\n", cur_rssi);
2373 ALOGD("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
2374 cur_bssid[0], cur_bssid[1], cur_bssid[2],
2375 cur_bssid[3], cur_bssid[4], cur_bssid[5]);
2376 JNIHelper helper(mVM);
2377 //ALOGD("onRssiThresholdbreached called, vm = %p, obj = %p, env = %p", mVM, mCls, env);
2378 helper.reportEvent(mCls, "onRssiThresholdBreached", "(IB)V", id, cur_rssi);
2379 }
2380
android_net_wifi_start_rssi_monitoring_native(JNIEnv * env,jclass cls,jint iface,jint idx,jbyte maxRssi,jbyte minRssi)2381 static jint android_net_wifi_start_rssi_monitoring_native(JNIEnv *env, jclass cls, jint iface,
2382 jint idx, jbyte maxRssi, jbyte minRssi) {
2383
2384 JNIHelper helper(env);
2385 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
2386 ALOGD("Start Rssi monitoring = %p", handle);
2387 ALOGD("MinRssi %d MaxRssi %d", minRssi, maxRssi);
2388 wifi_error ret;
2389 wifi_request_id id = idx;
2390 wifi_rssi_event_handler eh;
2391 eh.on_rssi_threshold_breached = onRssiThresholdbreached;
2392 ret = hal_fn.wifi_start_rssi_monitoring(id, handle, maxRssi, minRssi, eh);
2393 return ret;
2394 }
2395
android_net_wifi_stop_rssi_monitoring_native(JNIEnv * env,jclass cls,jint iface,jint idx)2396 static jint android_net_wifi_stop_rssi_monitoring_native(JNIEnv *env, jclass cls,
2397 jint iface, jint idx) {
2398 JNIHelper helper(env);
2399 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
2400 ALOGD("Stop Rssi monitoring = %p", handle);
2401 wifi_error ret;
2402 wifi_request_id id = idx;
2403 ret = hal_fn.wifi_stop_rssi_monitoring(id, handle);
2404 return ret;
2405 }
2406
android_net_wifi_get_wlan_wake_reason_count(JNIEnv * env,jclass cls,jint iface)2407 static jobject android_net_wifi_get_wlan_wake_reason_count(JNIEnv *env, jclass cls, jint iface) {
2408
2409 JNIHelper helper(env);
2410 WLAN_DRIVER_WAKE_REASON_CNT wake_reason_cnt;
2411 int cmd_event_wake_cnt_array[WAKE_REASON_TYPE_MAX];
2412 int driver_fw_local_wake_cnt_array[WAKE_REASON_TYPE_MAX];
2413 wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
2414 wifi_error ret;
2415
2416 wake_reason_cnt.cmd_event_wake_cnt = cmd_event_wake_cnt_array;
2417 wake_reason_cnt.cmd_event_wake_cnt_sz = WAKE_REASON_TYPE_MAX;
2418 wake_reason_cnt.cmd_event_wake_cnt_used = 0;
2419
2420 wake_reason_cnt.driver_fw_local_wake_cnt = driver_fw_local_wake_cnt_array;
2421 wake_reason_cnt.driver_fw_local_wake_cnt_sz = WAKE_REASON_TYPE_MAX;
2422 wake_reason_cnt.driver_fw_local_wake_cnt_used = 0;
2423
2424 ret = hal_fn.wifi_get_wake_reason_stats(handle, &wake_reason_cnt);
2425
2426 if (ret != WIFI_SUCCESS) {
2427 ALOGE("android_net_wifi_get_wlan_wake_reason_count: failed to get wake reason count\n");
2428 return NULL;
2429 }
2430
2431 JNIObject<jobject> stats = helper.createObject( "android/net/wifi/WifiWakeReasonAndCounts");
2432 if (stats == NULL) {
2433 ALOGE("android_net_wifi_get_wlan_wake_reason_count: error allocating object\n");
2434 return NULL;
2435 }
2436 JNIObject<jintArray> cmd_wake_arr =
2437 helper.newIntArray(wake_reason_cnt.cmd_event_wake_cnt_used);
2438 if (cmd_wake_arr == NULL) {
2439 ALOGE("android_net_wifi_get_wlan_wake_reason_count: error allocating array object\n");
2440 return NULL;
2441 }
2442 JNIObject<jintArray> local_wake_arr =
2443 helper.newIntArray(wake_reason_cnt.driver_fw_local_wake_cnt_used);
2444 if (local_wake_arr == NULL) {
2445 ALOGE("android_net_wifi_get_wlan_wake_reason_count: error allocating array object\n");
2446 return NULL;
2447 }
2448
2449 helper.setIntField(stats, "totalCmdEventWake", wake_reason_cnt.total_cmd_event_wake);
2450 helper.setIntField(stats, "totalDriverFwLocalWake", wake_reason_cnt.total_driver_fw_local_wake);
2451 helper.setIntField(stats, "totalRxDataWake", wake_reason_cnt.total_rx_data_wake);
2452 helper.setIntField(stats, "rxUnicast", wake_reason_cnt.rx_wake_details.rx_unicast_cnt);
2453 helper.setIntField(stats, "rxMulticast", wake_reason_cnt.rx_wake_details.rx_multicast_cnt);
2454 helper.setIntField(stats, "rxBroadcast", wake_reason_cnt.rx_wake_details.rx_broadcast_cnt);
2455 helper.setIntField(stats, "icmp", wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt);
2456 helper.setIntField(stats, "icmp6", wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt);
2457 helper.setIntField(stats, "icmp6Ra", wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra);
2458 helper.setIntField(stats, "icmp6Na", wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na);
2459 helper.setIntField(stats, "icmp6Ns", wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns);
2460 helper.setIntField(stats, "ipv4RxMulticast",
2461 wake_reason_cnt.rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt);
2462 helper.setIntField(stats, "ipv6Multicast",
2463 wake_reason_cnt.rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt);
2464 helper.setIntField(stats, "otherRxMulticast",
2465 wake_reason_cnt.rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt);
2466 helper.setIntArrayRegion(cmd_wake_arr, 0, wake_reason_cnt.cmd_event_wake_cnt_used,
2467 wake_reason_cnt.cmd_event_wake_cnt);
2468 helper.setIntArrayRegion(local_wake_arr, 0, wake_reason_cnt.driver_fw_local_wake_cnt_used,
2469 wake_reason_cnt.driver_fw_local_wake_cnt);
2470 helper.setObjectField(stats, "cmdEventWakeCntArray", "[I", cmd_wake_arr);
2471 helper.setObjectField(stats, "driverFWLocalWakeCntArray", "[I", local_wake_arr);
2472 return stats.detach();
2473 }
2474
android_net_wifi_readKernelLog(JNIEnv * env,jclass cls)2475 static jbyteArray android_net_wifi_readKernelLog(JNIEnv *env, jclass cls) {
2476 JNIHelper helper(env);
2477 ALOGV("Reading kernel logs");
2478
2479 int size = klogctl(/* SYSLOG_ACTION_SIZE_BUFFER */ 10, 0, 0);
2480 if (size < 1) {
2481 ALOGD("no kernel logs");
2482 return helper.newByteArray(0).detach();
2483 }
2484
2485 char *buf = (char *)malloc(size);
2486 if (buf == NULL) {
2487 ALOGD("can't allocate temporary storage");
2488 return helper.newByteArray(0).detach();
2489 }
2490
2491 int read = klogctl(/* SYSLOG_ACTION_READ_ALL */ 3, buf, size);
2492 if (read < 0) {
2493 ALOGD("can't read logs - %d", read);
2494 free(buf);
2495 return helper.newByteArray(0).detach();
2496 } else {
2497 ALOGV("read %d bytes", read);
2498 }
2499
2500 if (read != size) {
2501 ALOGV("read %d bytes, expecting %d", read, size);
2502 }
2503
2504 JNIObject<jbyteArray> result = helper.newByteArray(read);
2505 if (result.isNull()) {
2506 ALOGD("can't allocate array");
2507 free(buf);
2508 return result.detach();
2509 }
2510
2511 helper.setByteArrayRegion(result, 0, read, (jbyte*)buf);
2512 free(buf);
2513 return result.detach();
2514 }
2515
android_net_wifi_configure_nd_offload(JNIEnv * env,jclass cls,jint iface,jboolean enable)2516 static jint android_net_wifi_configure_nd_offload(JNIEnv *env, jclass cls,
2517 jint iface, jboolean enable) {
2518 JNIHelper helper(env);
2519 return hal_fn.wifi_configure_nd_offload(
2520 getIfaceHandle(helper, cls, iface),
2521 static_cast<int>(enable));
2522 }
2523
2524
2525 // ----------------------------------------------------------------------------
2526
2527 /*
2528 * JNI registration.
2529 */
2530 static JNINativeMethod gWifiMethods[] = {
2531 /* name, signature, funcPtr */
2532
2533 { "loadDriverNative", "()Z", (void *)android_net_wifi_loadDriver },
2534 { "isDriverLoadedNative", "()Z", (void *)android_net_wifi_isDriverLoaded },
2535 { "unloadDriverNative", "()Z", (void *)android_net_wifi_unloadDriver },
2536 { "startSupplicantNative", "(Z)Z", (void *)android_net_wifi_startSupplicant },
2537 { "killSupplicantNative", "(Z)Z", (void *)android_net_wifi_killSupplicant },
2538 { "connectToSupplicantNative", "()Z", (void *)android_net_wifi_connectToSupplicant },
2539 { "closeSupplicantConnectionNative", "()V",
2540 (void *)android_net_wifi_closeSupplicantConnection },
2541 { "waitForEventNative", "()Ljava/lang/String;", (void*)android_net_wifi_waitForEvent },
2542 { "doBooleanCommandNative", "(Ljava/lang/String;)Z", (void*)android_net_wifi_doBooleanCommand },
2543 { "doIntCommandNative", "(Ljava/lang/String;)I", (void*)android_net_wifi_doIntCommand },
2544 { "doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;",
2545 (void*) android_net_wifi_doStringCommand },
2546 { "startHalNative", "()Z", (void*) android_net_wifi_startHal },
2547 { "stopHalNative", "()V", (void*) android_net_wifi_stopHal },
2548 { "waitForHalEventNative", "()V", (void*) android_net_wifi_waitForHalEvents },
2549 { "getInterfacesNative", "()I", (void*) android_net_wifi_getInterfaces},
2550 { "getInterfaceNameNative", "(I)Ljava/lang/String;", (void*) android_net_wifi_getInterfaceName},
2551 { "getScanCapabilitiesNative", "(ILcom/android/server/wifi/WifiNative$ScanCapabilities;)Z",
2552 (void *) android_net_wifi_getScanCapabilities},
2553 { "startScanNative", "(IILcom/android/server/wifi/WifiNative$ScanSettings;)Z",
2554 (void*) android_net_wifi_startScan},
2555 { "stopScanNative", "(II)Z", (void*) android_net_wifi_stopScan},
2556 { "getScanResultsNative", "(IZ)[Landroid/net/wifi/WifiScanner$ScanData;",
2557 (void *) android_net_wifi_getScanResults},
2558 { "setHotlistNative", "(IILandroid/net/wifi/WifiScanner$HotlistSettings;)Z",
2559 (void*) android_net_wifi_setHotlist},
2560 { "resetHotlistNative", "(II)Z", (void*) android_net_wifi_resetHotlist},
2561 { "trackSignificantWifiChangeNative", "(IILandroid/net/wifi/WifiScanner$WifiChangeSettings;)Z",
2562 (void*) android_net_wifi_trackSignificantWifiChange},
2563 { "untrackSignificantWifiChangeNative", "(II)Z",
2564 (void*) android_net_wifi_untrackSignificantWifiChange},
2565 { "getWifiLinkLayerStatsNative", "(I)Landroid/net/wifi/WifiLinkLayerStats;",
2566 (void*) android_net_wifi_getLinkLayerStats},
2567 { "setWifiLinkLayerStatsNative", "(II)V",
2568 (void*) android_net_wifi_setLinkLayerStats},
2569 { "getSupportedFeatureSetNative", "(I)I",
2570 (void*) android_net_wifi_getSupportedFeatures},
2571 { "requestRangeNative", "(II[Landroid/net/wifi/RttManager$RttParams;)Z",
2572 (void*) android_net_wifi_requestRange},
2573 { "cancelRangeRequestNative", "(II[Landroid/net/wifi/RttManager$RttParams;)Z",
2574 (void*) android_net_wifi_cancelRange},
2575 { "enableRttResponderNative",
2576 "(IIILcom/android/server/wifi/WifiNative$WifiChannelInfo;)Landroid/net/wifi/RttManager$ResponderConfig;",
2577 (void*) android_net_wifi_enableResponder},
2578 { "disableRttResponderNative", "(II)Z",
2579 (void*) android_net_wifi_disableResponder},
2580
2581 { "setScanningMacOuiNative", "(I[B)Z", (void*) android_net_wifi_setScanningMacOui},
2582 { "getChannelsForBandNative", "(II)[I", (void*) android_net_wifi_getValidChannels},
2583 { "setDfsFlagNative", "(IZ)Z", (void*) android_net_wifi_setDfsFlag},
2584 { "setInterfaceUpNative", "(Z)Z", (void*) android_net_wifi_set_interface_up},
2585 { "getRttCapabilitiesNative", "(I)Landroid/net/wifi/RttManager$RttCapabilities;",
2586 (void*) android_net_wifi_get_rtt_capabilities},
2587 { "getApfCapabilitiesNative", "(I)Landroid/net/apf/ApfCapabilities;",
2588 (void*) android_net_wifi_get_apf_capabilities},
2589 { "installPacketFilterNative", "(I[B)Z", (void*) android_net_wifi_install_packet_filter},
2590 {"setCountryCodeHalNative", "(ILjava/lang/String;)Z",
2591 (void*) android_net_wifi_set_Country_Code_Hal},
2592 { "setPnoListNative", "(IILcom/android/server/wifi/WifiNative$PnoSettings;)Z",
2593 (void*) android_net_wifi_setPnoListNative},
2594 { "resetPnoListNative", "(II)Z", (void*) android_net_wifi_resetPnoListNative},
2595 {"enableDisableTdlsNative", "(IZLjava/lang/String;)Z",
2596 (void*) android_net_wifi_enable_disable_tdls},
2597 {"getTdlsStatusNative", "(ILjava/lang/String;)Lcom/android/server/wifi/WifiNative$TdlsStatus;",
2598 (void*) android_net_wifi_get_tdls_status},
2599 {"getTdlsCapabilitiesNative", "(I)Lcom/android/server/wifi/WifiNative$TdlsCapabilities;",
2600 (void*) android_net_wifi_get_tdls_capabilities},
2601 {"getSupportedLoggerFeatureSetNative","(I)I",
2602 (void*) android_net_wifi_get_supported_logger_feature},
2603 {"getDriverVersionNative", "(I)Ljava/lang/String;",
2604 (void*) android_net_wifi_get_driver_version},
2605 {"getFirmwareVersionNative", "(I)Ljava/lang/String;",
2606 (void*) android_net_wifi_get_firmware_version},
2607 {"getRingBufferStatusNative", "(I)[Lcom/android/server/wifi/WifiNative$RingBufferStatus;",
2608 (void*) android_net_wifi_get_ring_buffer_status},
2609 {"startLoggingRingBufferNative", "(IIIIILjava/lang/String;)Z",
2610 (void*) android_net_wifi_start_logging_ring_buffer},
2611 {"getRingBufferDataNative", "(ILjava/lang/String;)Z",
2612 (void*) android_net_wifi_get_ring_buffer_data},
2613 {"getFwMemoryDumpNative","(I)Z", (void*) android_net_wifi_get_fw_memory_dump},
2614 {"getDriverStateDumpNative","(I)[B", (void*) android_net_wifi_get_driver_state_dump},
2615 { "setBssidBlacklistNative", "(II[Ljava/lang/String;)Z",
2616 (void*)android_net_wifi_setBssidBlacklist},
2617 {"setLoggingEventHandlerNative", "(II)Z", (void *) android_net_wifi_set_log_handler},
2618 {"resetLogHandlerNative", "(II)Z", (void *) android_net_wifi_reset_log_handler},
2619 {"startPktFateMonitoringNative", "(I)I", (void*) android_net_wifi_start_pkt_fate_monitoring},
2620 {"getTxPktFatesNative", "(I[Lcom/android/server/wifi/WifiNative$TxFateReport;)I",
2621 (void*) android_net_wifi_get_tx_pkt_fates},
2622 {"getRxPktFatesNative", "(I[Lcom/android/server/wifi/WifiNative$RxFateReport;)I",
2623 (void*) android_net_wifi_get_rx_pkt_fates},
2624 { "startSendingOffloadedPacketNative", "(II[B[B[BI)I",
2625 (void*)android_net_wifi_start_sending_offloaded_packet},
2626 { "stopSendingOffloadedPacketNative", "(II)I",
2627 (void*)android_net_wifi_stop_sending_offloaded_packet},
2628 {"startRssiMonitoringNative", "(IIBB)I",
2629 (void*)android_net_wifi_start_rssi_monitoring_native},
2630 {"stopRssiMonitoringNative", "(II)I",
2631 (void*)android_net_wifi_stop_rssi_monitoring_native},
2632 { "getWlanWakeReasonCountNative", "(I)Landroid/net/wifi/WifiWakeReasonAndCounts;",
2633 (void*) android_net_wifi_get_wlan_wake_reason_count},
2634 {"isGetChannelsForBandSupportedNative", "()Z",
2635 (void*)android_net_wifi_is_get_channels_for_band_supported},
2636 {"readKernelLogNative", "()[B", (void*)android_net_wifi_readKernelLog},
2637 {"configureNeighborDiscoveryOffload", "(IZ)I", (void*)android_net_wifi_configure_nd_offload},
2638 };
2639
2640 /* User to register native functions */
2641 extern "C"
Java_com_android_server_wifi_WifiNative_registerNatives(JNIEnv * env,jclass clazz)2642 jint Java_com_android_server_wifi_WifiNative_registerNatives(JNIEnv* env, jclass clazz) {
2643 // initialization needed for unit test APK
2644 JniConstants::init(env);
2645
2646 return jniRegisterNativeMethods(env,
2647 "com/android/server/wifi/WifiNative", gWifiMethods, NELEM(gWifiMethods));
2648 }
2649
2650 }; // namespace android
2651