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