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
46namespace android {
47
48extern "C"
49jint Java_com_android_server_wifi_WifiNative_registerNanNatives(JNIEnv* env, jclass clazz);
50
51static jint DBG = false;
52
53//Please put all HAL function call here and call from the function table instead of directly call
54wifi_hal_fn hal_fn;
55static 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
80static 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
88static 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.
102static 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
110static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jclass)
111{
112    return (::is_wifi_driver_loaded() == 1);
113}
114
115static jboolean android_net_wifi_loadDriver(JNIEnv* env, jclass)
116{
117    return (::wifi_load_driver() == 0);
118}
119
120static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jclass)
121{
122    return (::wifi_unload_driver() == 0);
123}
124
125static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jclass, jboolean p2pSupported)
126{
127    return (::wifi_start_supplicant(p2pSupported) == 0);
128}
129
130static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jclass, jboolean p2pSupported)
131{
132    return (::wifi_stop_supplicant(p2pSupported) == 0);
133}
134
135static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jclass)
136{
137    return (::wifi_connect_to_supplicant() == 0);
138}
139
140static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jclass)
141{
142    ::wifi_close_supplicant_connection();
143}
144
145static 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
156static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jclass, jstring javaCommand) {
157    return doBooleanCommand(env, javaCommand);
158}
159
160static jint android_net_wifi_doIntCommand(JNIEnv* env, jclass, jstring javaCommand) {
161    return doIntCommand(env, javaCommand);
162}
163
164static jstring android_net_wifi_doStringCommand(JNIEnv* env, jclass, jstring javaCommand) {
165    return doStringCommand(env,javaCommand);
166}
167
168/* wifi_hal <==> WifiNative bridge */
169
170static jclass mCls;                             /* saved WifiNative object */
171static JavaVM *mVM;                             /* saved JVM pointer */
172
173static const char *WifiHandleVarName = "sWifiHalHandle";
174static const char *WifiIfaceHandleVarName = "sWifiIfaceHandles";
175
176wifi_handle getWifiHandle(JNIHelper &helper, jclass cls) {
177    return (wifi_handle) helper.getStaticLongField(cls, WifiHandleVarName);
178}
179
180wifi_interface_handle getIfaceHandle(JNIHelper &helper, jclass cls, jint index) {
181    return (wifi_interface_handle) helper.getStaticLongArrayField(cls, WifiIfaceHandleVarName, index);
182}
183
184jboolean 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}
199static 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
239int 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
292static jboolean android_net_wifi_set_interface_up(JNIEnv* env, jclass cls, jboolean up) {
293    return (set_iface_flags("wlan0", (bool)up) == 0);
294}
295
296static 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
331void 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
342static 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
354static 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
364static 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
408static 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
426static 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
435static 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
452static 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
529static 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
538static 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
544static 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
613static 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
647static 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
660static 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
680static 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
689static 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
708static 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
738static 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
769static 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
828static 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
837void 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
882static 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
948static 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
958wifi_iface_stat link_stat;
959wifi_radio_stat radio_stat; // L release has support for only one radio
960u32 *tx_time_per_level_arr = 0;
961// Let's cache the supported feature set to avoid unnecessary HAL invocations.
962feature_set cached_feature_set = 0;
963
964bool 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
975void 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
1002static 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
1015static 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
1083static 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
1112static 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
1199const int MaxRttConfigs = 16;
1200
1201static 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
1270static 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
1304static 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
1354static 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
1363static 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
1387static 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
1391static 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
1419static 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
1430static 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
1472static 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
1507static 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
1519static 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
1533static 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
1551static 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
1567static 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
1593static 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// ----------------------------------------------------------------------------
1630static jint android_net_wifi_get_supported_logger_feature(JNIEnv *env, jclass cls, jint iface){
1631    //Not implemented yet
1632    return -1;
1633}
1634
1635static 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
1666static 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
1697static 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
1759static 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
1797static 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
1814static 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
1840static 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
1854static 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
1868static 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
1886std::vector<jbyte>* driver_state_dump_buffer_for_callback = nullptr;
1887
1888static void on_driver_state_dump(char *buffer, int buffer_size);
1889static wifi_driver_memory_dump_callbacks driver_state_dump_callbacks = {
1890    on_driver_state_dump
1891};
1892
1893static 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
1907static 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
1943static 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
1970static 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
1994static 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().
2002template<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
2018template<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
2033template<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
2109static 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
2117static 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
2130static 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
2176static 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
2263static 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
2277static 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
2325static 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
2359static 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
2370static 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
2381static 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
2396static 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
2407static 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
2475static 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
2516static 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 */
2530static 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 */
2641extern "C"
2642jint 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