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(&params, 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(&params, 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(&params, 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(&params, 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, &params, 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(&params, 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