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 <android_runtime/AndroidRuntime.h>
     25 #include <utils/Log.h>
     26 #include <utils/String16.h>
     27 #include <ctype.h>
     28 #include <sys/socket.h>
     29 #include <linux/if.h>
     30 #include "wifi.h"
     31 #include "wifi_hal.h"
     32 #include "jni_helper.h"
     33 #include "rtt.h"
     34 #include "wifi_hal_stub.h"
     35 #define REPLY_BUF_SIZE 4096 // wpa_supplicant's maximum size.
     36 #define EVENT_BUF_SIZE 2048
     37 
     38 namespace android {
     39 
     40 static jint DBG = false;
     41 
     42 //Please put all HAL function call here and call from the function table instead of directly call
     43 static wifi_hal_fn hal_fn;
     44 int init_wifi_hal_func_table(wifi_hal_fn *hal_fn) {
     45     if (hal_fn == NULL) {
     46         return -1;
     47     }
     48     hal_fn->wifi_initialize = wifi_initialize_stub;
     49     hal_fn->wifi_cleanup = wifi_cleanup_stub;
     50     hal_fn->wifi_event_loop = wifi_event_loop_stub;
     51     hal_fn->wifi_get_error_info = wifi_get_error_info_stub;
     52     hal_fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set_stub;
     53     hal_fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix_stub;
     54     hal_fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui_stub;
     55     hal_fn->wifi_get_supported_channels = wifi_get_supported_channels_stub;
     56     hal_fn->wifi_is_epr_supported = wifi_is_epr_supported_stub;
     57     hal_fn->wifi_get_ifaces = wifi_get_ifaces_stub;
     58     hal_fn->wifi_get_iface_name = wifi_get_iface_name_stub;
     59     hal_fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler_stub;
     60     hal_fn->wifi_start_gscan = wifi_start_gscan_stub;
     61     hal_fn->wifi_stop_gscan = wifi_stop_gscan_stub;
     62     hal_fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results_stub;
     63     hal_fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist_stub;
     64     hal_fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist_stub;
     65     hal_fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler_stub;
     66     hal_fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler_stub;
     67     hal_fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities_stub;
     68     hal_fn->wifi_set_link_stats = wifi_set_link_stats_stub;
     69     hal_fn->wifi_get_link_stats = wifi_get_link_stats_stub;
     70     hal_fn->wifi_clear_link_stats = wifi_clear_link_stats_stub;
     71     hal_fn->wifi_get_valid_channels = wifi_get_valid_channels_stub;
     72     hal_fn->wifi_rtt_range_request = wifi_rtt_range_request_stub;
     73     hal_fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel_stub;
     74     hal_fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities_stub;
     75     hal_fn->wifi_start_logging = wifi_start_logging_stub;
     76     hal_fn->wifi_set_epno_list = wifi_set_epno_list_stub;
     77     hal_fn->wifi_set_country_code = wifi_set_country_code_stub;
     78     hal_fn->wifi_enable_tdls = wifi_enable_tdls_stub;
     79     hal_fn->wifi_disable_tdls = wifi_disable_tdls_stub;
     80     hal_fn->wifi_get_tdls_status = wifi_get_tdls_status_stub;
     81     hal_fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities_stub;
     82     hal_fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag_stub;
     83     hal_fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump_stub;
     84     hal_fn->wifi_set_log_handler = wifi_set_log_handler_stub;
     85     hal_fn->wifi_reset_log_handler = wifi_reset_log_handler_stub;
     86     hal_fn->wifi_set_alert_handler = wifi_set_alert_handler_stub;
     87     hal_fn->wifi_reset_alert_handler = wifi_reset_alert_handler_stub;
     88     hal_fn->wifi_get_firmware_version = wifi_get_firmware_version_stub;
     89     hal_fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status_stub;
     90     hal_fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set_stub;
     91     hal_fn->wifi_get_ring_data = wifi_get_ring_data_stub;
     92     hal_fn->wifi_get_driver_version = wifi_get_driver_version_stub;
     93     hal_fn->wifi_set_ssid_white_list = wifi_set_ssid_white_list_stub;
     94     hal_fn->wifi_set_gscan_roam_params = wifi_set_gscan_roam_params_stub;
     95     hal_fn->wifi_set_bssid_preference = wifi_set_bssid_preference_stub;
     96     hal_fn->wifi_enable_lazy_roam = wifi_enable_lazy_roam_stub;
     97     hal_fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist_stub;
     98     hal_fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet_stub;
     99     hal_fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet_stub;
    100     return 0;
    101 }
    102 
    103 static bool doCommand(JNIEnv* env, jstring javaCommand,
    104                       char* reply, size_t reply_len) {
    105     ScopedUtfChars command(env, javaCommand);
    106     if (command.c_str() == NULL) {
    107         return false; // ScopedUtfChars already threw on error.
    108     }
    109 
    110     if (DBG) {
    111         ALOGD("doCommand: %s", command.c_str());
    112     }
    113 
    114     --reply_len; // Ensure we have room to add NUL termination.
    115     if (::wifi_command(command.c_str(), reply, &reply_len) != 0) {
    116         return false;
    117     }
    118 
    119     // Strip off trailing newline.
    120     if (reply_len > 0 && reply[reply_len-1] == '\n') {
    121         reply[reply_len-1] = '\0';
    122     } else {
    123         reply[reply_len] = '\0';
    124     }
    125     return true;
    126 }
    127 
    128 static jint doIntCommand(JNIEnv* env, jstring javaCommand) {
    129     char reply[REPLY_BUF_SIZE];
    130     if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
    131         return -1;
    132     }
    133     return static_cast<jint>(atoi(reply));
    134 }
    135 
    136 static jboolean doBooleanCommand(JNIEnv* env, jstring javaCommand) {
    137     char reply[REPLY_BUF_SIZE];
    138     if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
    139         return JNI_FALSE;
    140     }
    141     return (strcmp(reply, "OK") == 0);
    142 }
    143 
    144 // Send a command to the supplicant, and return the reply as a String.
    145 static jstring doStringCommand(JNIEnv* env, jstring javaCommand) {
    146     char reply[REPLY_BUF_SIZE];
    147     if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
    148         return NULL;
    149     }
    150     return env->NewStringUTF(reply);
    151 }
    152 
    153 static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject)
    154 {
    155     return (::is_wifi_driver_loaded() == 1);
    156 }
    157 
    158 static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
    159 {
    160     return (::wifi_load_driver() == 0);
    161 }
    162 
    163 static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject)
    164 {
    165     return (::wifi_unload_driver() == 0);
    166 }
    167 
    168 static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject, jboolean p2pSupported)
    169 {
    170     return (::wifi_start_supplicant(p2pSupported) == 0);
    171 }
    172 
    173 static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject, jboolean p2pSupported)
    174 {
    175     return (::wifi_stop_supplicant(p2pSupported) == 0);
    176 }
    177 
    178 static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject)
    179 {
    180     return (::wifi_connect_to_supplicant() == 0);
    181 }
    182 
    183 static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject)
    184 {
    185     ::wifi_close_supplicant_connection();
    186 }
    187 
    188 static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject)
    189 {
    190     char buf[EVENT_BUF_SIZE];
    191     int nread = ::wifi_wait_for_event(buf, sizeof buf);
    192     if (nread > 0) {
    193         return env->NewStringUTF(buf);
    194     } else {
    195         return NULL;
    196     }
    197 }
    198 
    199 static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring javaCommand) {
    200     return doBooleanCommand(env, javaCommand);
    201 }
    202 
    203 static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring javaCommand) {
    204     return doIntCommand(env, javaCommand);
    205 }
    206 
    207 static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring javaCommand) {
    208     return doStringCommand(env,javaCommand);
    209 }
    210 
    211 /* wifi_hal <==> WifiNative bridge */
    212 
    213 static jclass mCls;                             /* saved WifiNative object */
    214 static JavaVM *mVM;                             /* saved JVM pointer */
    215 
    216 static const char *WifiHandleVarName = "sWifiHalHandle";
    217 static const char *WifiIfaceHandleVarName = "sWifiIfaceHandles";
    218 static jmethodID OnScanResultsMethodID;
    219 
    220 static wifi_handle getWifiHandle(JNIHelper &helper, jclass cls) {
    221     return (wifi_handle) helper.getStaticLongField(cls, WifiHandleVarName);
    222 }
    223 
    224 static wifi_interface_handle getIfaceHandle(JNIHelper &helper, jclass cls, jint index) {
    225     return (wifi_interface_handle) helper.getStaticLongArrayField(cls, WifiIfaceHandleVarName, index);
    226 }
    227 
    228 jboolean setSSIDField(JNIHelper helper, jobject scanResult, const char *rawSsid) {
    229 
    230     int len = strlen(rawSsid);
    231 
    232     if (len > 0) {
    233         JNIObject<jbyteArray> ssidBytes = helper.newByteArray(len);
    234         helper.setByteArrayRegion(ssidBytes, 0, len, (jbyte *) rawSsid);
    235         jboolean ret = helper.callStaticMethod(mCls,
    236                 "setSsid", "([BLandroid/net/wifi/ScanResult;)Z", ssidBytes.get(), scanResult);
    237         return ret;
    238     } else {
    239         //empty SSID or SSID start with \0
    240         return true;
    241     }
    242 }
    243 static JNIObject<jobject> createScanResult(JNIHelper &helper, wifi_scan_result *result) {
    244 
    245     // ALOGD("creating scan result");
    246 
    247     JNIObject<jobject> scanResult = helper.createObject("android/net/wifi/ScanResult");
    248     if (scanResult == NULL) {
    249         ALOGE("Error in creating scan result");
    250         return JNIObject<jobject>(helper, NULL);
    251     }
    252 
    253     ALOGV("setting SSID to %s", result->ssid);
    254 
    255     if (!setSSIDField(helper, scanResult, result->ssid)) {
    256         ALOGE("Error on set SSID");
    257         return JNIObject<jobject>(helper, NULL);
    258     }
    259 
    260     char bssid[32];
    261     sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result->bssid[0], result->bssid[1],
    262         result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]);
    263 
    264     helper.setStringField(scanResult, "BSSID", bssid);
    265 
    266     helper.setIntField(scanResult, "level", result->rssi);
    267     helper.setIntField(scanResult, "frequency", result->channel);
    268     helper.setLongField(scanResult, "timestamp", result->ts);
    269 
    270     return scanResult;
    271 }
    272 
    273 int set_iface_flags(const char *ifname, int dev_up) {
    274     struct ifreq ifr;
    275     int ret;
    276     int sock = socket(PF_INET, SOCK_DGRAM, 0);
    277     if (sock < 0) {
    278         ALOGD("Bad socket: %d\n", sock);
    279         return -errno;
    280     }
    281 
    282     //ALOGD("setting interface %s flags (%s)\n", ifname, dev_up ? "UP" : "DOWN");
    283 
    284     memset(&ifr, 0, sizeof(ifr));
    285     strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
    286 
    287     //ALOGD("reading old value\n");
    288 
    289     if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
    290       ret = errno ? -errno : -999;
    291       ALOGE("Could not read interface %s flags: %d\n", ifname, errno);
    292       close(sock);
    293       return ret;
    294     } else {
    295       //ALOGD("writing new value\n");
    296     }
    297 
    298     if (dev_up) {
    299       if (ifr.ifr_flags & IFF_UP) {
    300         // ALOGD("interface %s is already up\n", ifname);
    301         close(sock);
    302         return 0;
    303       }
    304       ifr.ifr_flags |= IFF_UP;
    305     } else {
    306       if (!(ifr.ifr_flags & IFF_UP)) {
    307         // ALOGD("interface %s is already down\n", ifname);
    308         close(sock);
    309         return 0;
    310       }
    311       ifr.ifr_flags &= ~IFF_UP;
    312     }
    313 
    314     if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
    315       ALOGE("Could not set interface %s flags: %d\n", ifname, errno);
    316       ret = errno ? -errno : -999;
    317       close(sock);
    318       return ret;
    319     } else {
    320       ALOGD("set interface %s flags (%s)\n", ifname, dev_up ? "UP" : "DOWN");
    321     }
    322     close(sock);
    323     return 0;
    324 }
    325 
    326 static jboolean android_net_wifi_toggle_interface(JNIEnv* env, jclass cls, int toggle) {
    327     return(set_iface_flags("wlan0", toggle) == 0);
    328 }
    329 
    330 static jboolean android_net_wifi_startHal(JNIEnv* env, jclass cls) {
    331     JNIHelper helper(env);
    332     wifi_handle halHandle = getWifiHandle(helper, cls);
    333     if (halHandle == NULL) {
    334 
    335         if(init_wifi_hal_func_table(&hal_fn) != 0 ) {
    336             ALOGD("Can not initialize the basic function pointer table");
    337             return false;
    338         }
    339 
    340         wifi_error res = init_wifi_vendor_hal_func_table(&hal_fn);
    341         if (res != WIFI_SUCCESS) {
    342             ALOGD("Can not initialize the vendor function pointer table");
    343 	    return false;
    344         }
    345 
    346         int ret = set_iface_flags("wlan0", 1);
    347         if(ret != 0) {
    348             return false;
    349         }
    350 
    351         res = hal_fn.wifi_initialize(&halHandle);
    352         if (res == WIFI_SUCCESS) {
    353             helper.setStaticLongField(cls, WifiHandleVarName, (jlong)halHandle);
    354             ALOGD("Did set static halHandle = %p", halHandle);
    355         }
    356         env->GetJavaVM(&mVM);
    357         mCls = (jclass) env->NewGlobalRef(cls);
    358         ALOGD("halHandle = %p, mVM = %p, mCls = %p", halHandle, mVM, mCls);
    359         return res == WIFI_SUCCESS;
    360     } else {
    361         return (set_iface_flags("wlan0", 1) == 0);
    362     }
    363 }
    364 
    365 void android_net_wifi_hal_cleaned_up_handler(wifi_handle handle) {
    366     ALOGD("In wifi cleaned up handler");
    367 
    368     JNIHelper helper(mVM);
    369     helper.setStaticLongField(mCls, WifiHandleVarName, 0);
    370 
    371     helper.deleteGlobalRef(mCls);
    372     mCls = NULL;
    373     mVM  = NULL;
    374 }
    375 
    376 static void android_net_wifi_stopHal(JNIEnv* env, jclass cls) {
    377     ALOGD("In wifi stop Hal");
    378 
    379     JNIHelper helper(env);
    380     wifi_handle halHandle = getWifiHandle(helper, cls);
    381     if (halHandle == NULL)
    382         return;
    383 
    384     ALOGD("halHandle = %p, mVM = %p, mCls = %p", halHandle, mVM, mCls);
    385     hal_fn.wifi_cleanup(halHandle, android_net_wifi_hal_cleaned_up_handler);
    386 }
    387 
    388 static void android_net_wifi_waitForHalEvents(JNIEnv* env, jclass cls) {
    389 
    390     ALOGD("waitForHalEvents called, vm = %p, obj = %p, env = %p", mVM, mCls, env);
    391 
    392     JNIHelper helper(env);
    393     wifi_handle halHandle = getWifiHandle(helper, cls);
    394     hal_fn.wifi_event_loop(halHandle);
    395     set_iface_flags("wlan0", 0);
    396 }
    397 
    398 static int android_net_wifi_getInterfaces(JNIEnv *env, jclass cls) {
    399     int n = 0;
    400 
    401     JNIHelper helper(env);
    402 
    403     wifi_handle halHandle = getWifiHandle(helper, cls);
    404     wifi_interface_handle *ifaceHandles = NULL;
    405     int result = hal_fn.wifi_get_ifaces(halHandle, &n, &ifaceHandles);
    406     if (result < 0) {
    407         return result;
    408     }
    409 
    410     if (n < 0) {
    411         THROW(helper,"android_net_wifi_getInterfaces no interfaces");
    412         return 0;
    413     }
    414 
    415     if (ifaceHandles == NULL) {
    416        THROW(helper,"android_net_wifi_getInterfaces null interface array");
    417        return 0;
    418     }
    419 
    420     if (n > 8) {
    421         THROW(helper,"Too many interfaces");
    422         return 0;
    423     }
    424 
    425     jlongArray array = (env)->NewLongArray(n);
    426     if (array == NULL) {
    427         THROW(helper,"Error in accessing array");
    428         return 0;
    429     }
    430 
    431     jlong elems[8];
    432     for (int i = 0; i < n; i++) {
    433         elems[i] = reinterpret_cast<jlong>(ifaceHandles[i]);
    434     }
    435 
    436     helper.setLongArrayRegion(array, 0, n, elems);
    437     helper.setStaticLongArrayField(cls, WifiIfaceHandleVarName, array);
    438 
    439     return (result < 0) ? result : n;
    440 }
    441 
    442 static jstring android_net_wifi_getInterfaceName(JNIEnv *env, jclass cls, jint i) {
    443 
    444     char buf[EVENT_BUF_SIZE];
    445 
    446     JNIHelper helper(env);
    447 
    448     jlong value = helper.getStaticLongArrayField(cls, WifiIfaceHandleVarName, i);
    449     wifi_interface_handle handle = (wifi_interface_handle) value;
    450     int result = hal_fn.wifi_get_iface_name(handle, buf, sizeof(buf));
    451     if (result < 0) {
    452         return NULL;
    453     } else {
    454         JNIObject<jstring> name = helper.newStringUTF(buf);
    455         return name.detach();
    456     }
    457 }
    458 
    459 
    460 static void onScanResultsAvailable(wifi_request_id id, unsigned num_results) {
    461 
    462     JNIHelper helper(mVM);
    463 
    464     // ALOGD("onScanResultsAvailable called, vm = %p, obj = %p, env = %p", mVM, mCls, env);
    465 
    466     helper.reportEvent(mCls, "onScanResultsAvailable", "(I)V", id);
    467 }
    468 
    469 static void onScanEvent(wifi_scan_event event, unsigned status) {
    470 
    471     JNIHelper helper(mVM);
    472 
    473     // ALOGD("onScanStatus called, vm = %p, obj = %p, env = %p", mVM, mCls, env);
    474 
    475     helper.reportEvent(mCls, "onScanStatus", "(I)V", event);
    476 }
    477 
    478 static void onFullScanResult(wifi_request_id id, wifi_scan_result *result) {
    479 
    480     JNIHelper helper(mVM);
    481 
    482     //ALOGD("onFullScanResult called, vm = %p, obj = %p, env = %p", mVM, mCls, env);
    483 
    484     JNIObject<jobject> scanResult = createScanResult(helper, result);
    485 
    486     //ALOGD("Creating a byte array of length %d", result->ie_length);
    487 
    488     JNIObject<jbyteArray> elements = helper.newByteArray(result->ie_length);
    489     if (elements == NULL) {
    490         ALOGE("Error in allocating array");
    491         return;
    492     }
    493 
    494     // ALOGD("Setting byte array");
    495 
    496     jbyte *bytes = (jbyte *)&(result->ie_data[0]);
    497     helper.setByteArrayRegion(elements, 0, result->ie_length, bytes);
    498 
    499     // ALOGD("Returning result");
    500 
    501     helper.reportEvent(mCls, "onFullScanResult", "(ILandroid/net/wifi/ScanResult;[B)V", id,
    502             scanResult.get(), elements.get());
    503 }
    504 
    505 static jboolean android_net_wifi_startScan(
    506         JNIEnv *env, jclass cls, jint iface, jint id, jobject settings) {
    507 
    508     JNIHelper helper(env);
    509     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
    510     // ALOGD("starting scan on interface[%d] = %p", iface, handle);
    511 
    512     wifi_scan_cmd_params params;
    513     memset(&params, 0, sizeof(params));
    514 
    515     params.base_period = helper.getIntField(settings, "base_period_ms");
    516     params.max_ap_per_scan = helper.getIntField(settings, "max_ap_per_scan");
    517     params.report_threshold_percent = helper.getIntField(settings, "report_threshold_percent");
    518     params.report_threshold_num_scans = helper.getIntField(settings, "report_threshold_num_scans");
    519 
    520     ALOGD("Initialized common fields %d, %d, %d, %d", params.base_period, params.max_ap_per_scan,
    521             params.report_threshold_percent, params.report_threshold_num_scans);
    522 
    523     const char *bucket_array_type = "[Lcom/android/server/wifi/WifiNative$BucketSettings;";
    524     const char *channel_array_type = "[Lcom/android/server/wifi/WifiNative$ChannelSettings;";
    525 
    526     params.num_buckets = helper.getIntField(settings, "num_buckets");
    527 
    528     // ALOGD("Initialized num_buckets to %d", params.num_buckets);
    529 
    530     for (int i = 0; i < params.num_buckets; i++) {
    531         JNIObject<jobject> bucket = helper.getObjectArrayField(
    532                 settings, "buckets", bucket_array_type, i);
    533 
    534         params.buckets[i].bucket = helper.getIntField(bucket, "bucket");
    535         params.buckets[i].band = (wifi_band) helper.getIntField(bucket, "band");
    536         params.buckets[i].period = helper.getIntField(bucket, "period_ms");
    537 
    538         int report_events = helper.getIntField(bucket, "report_events");
    539         params.buckets[i].report_events = report_events;
    540 
    541         ALOGD("bucket[%d] = %d:%d:%d:%d", i, params.buckets[i].bucket,
    542                 params.buckets[i].band, params.buckets[i].period, report_events);
    543 
    544         params.buckets[i].num_channels = helper.getIntField(bucket, "num_channels");
    545         // ALOGD("Initialized num_channels to %d", params.buckets[i].num_channels);
    546 
    547         for (int j = 0; j < params.buckets[i].num_channels; j++) {
    548             JNIObject<jobject> channel = helper.getObjectArrayField(
    549                     bucket, "channels", channel_array_type, j);
    550 
    551             params.buckets[i].channels[j].channel = helper.getIntField(channel, "frequency");
    552             params.buckets[i].channels[j].dwellTimeMs = helper.getIntField(channel, "dwell_time_ms");
    553 
    554             bool passive = helper.getBoolField(channel, "passive");
    555             params.buckets[i].channels[j].passive = (passive ? 1 : 0);
    556 
    557             // ALOGD("Initialized channel %d", params.buckets[i].channels[j].channel);
    558         }
    559     }
    560 
    561     // ALOGD("Initialized all fields");
    562 
    563     wifi_scan_result_handler handler;
    564     memset(&handler, 0, sizeof(handler));
    565     handler.on_scan_results_available = &onScanResultsAvailable;
    566     handler.on_full_scan_result = &onFullScanResult;
    567     handler.on_scan_event = &onScanEvent;
    568 
    569     return hal_fn.wifi_start_gscan(id, handle, params, handler) == WIFI_SUCCESS;
    570 }
    571 
    572 static jboolean android_net_wifi_stopScan(JNIEnv *env, jclass cls, jint iface, jint id) {
    573 
    574     JNIHelper helper(env);
    575     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
    576     // ALOGD("stopping scan on interface[%d] = %p", iface, handle);
    577 
    578     return hal_fn.wifi_stop_gscan(id, handle)  == WIFI_SUCCESS;
    579 }
    580 
    581 static int compare_scan_result_timestamp(const void *v1, const void *v2) {
    582     const wifi_scan_result *result1 = static_cast<const wifi_scan_result *>(v1);
    583     const wifi_scan_result *result2 = static_cast<const wifi_scan_result *>(v2);
    584     return result1->ts - result2->ts;
    585 }
    586 
    587 static jobject android_net_wifi_getScanResults(
    588         JNIEnv *env, jclass cls, jint iface, jboolean flush)  {
    589 
    590     JNIHelper helper(env);
    591     wifi_cached_scan_results scan_data[64];
    592     int num_scan_data = 64;
    593 
    594     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
    595     // ALOGD("getting scan results on interface[%d] = %p", iface, handle);
    596 
    597     byte b = flush ? 0xFF : 0;
    598     int result = hal_fn.wifi_get_cached_gscan_results(handle, b, num_scan_data, scan_data, &num_scan_data);
    599     if (result == WIFI_SUCCESS) {
    600         JNIObject<jobjectArray> scanData = helper.createObjectArray(
    601                 "android/net/wifi/WifiScanner$ScanData", num_scan_data);
    602         if (scanData == NULL) {
    603             ALOGE("Error in allocating array of scanData");
    604             return NULL;
    605         }
    606 
    607         for (int i = 0; i < num_scan_data; i++) {
    608 
    609             JNIObject<jobject> data = helper.createObject("android/net/wifi/WifiScanner$ScanData");
    610             if (data == NULL) {
    611                 ALOGE("Error in allocating scanData");
    612                 return NULL;
    613             }
    614 
    615             helper.setIntField(data, "mId", scan_data[i].scan_id);
    616             helper.setIntField(data, "mFlags", scan_data[i].flags);
    617 
    618             /* sort all scan results by timestamp */
    619             qsort(scan_data[i].results, scan_data[i].num_results,
    620                     sizeof(wifi_scan_result), compare_scan_result_timestamp);
    621 
    622             JNIObject<jobjectArray> scanResults = helper.createObjectArray(
    623                     "android/net/wifi/ScanResult", scan_data[i].num_results);
    624             if (scanResults == NULL) {
    625                 ALOGE("Error in allocating scanResult array");
    626                 return NULL;
    627             }
    628 
    629             wifi_scan_result *results = scan_data[i].results;
    630             for (int j = 0; j < scan_data[i].num_results; j++) {
    631 
    632                 JNIObject<jobject> scanResult = createScanResult(helper, &results[j]);
    633                 if (scanResult == NULL) {
    634                     ALOGE("Error in creating scan result");
    635                     return NULL;
    636                 }
    637 
    638                 helper.setObjectArrayElement(scanResults, j, scanResult);
    639             }
    640 
    641             helper.setObjectField(data, "mResults", "[Landroid/net/wifi/ScanResult;", scanResults);
    642             helper.setObjectArrayElement(scanData, i, data);
    643         }
    644 
    645         // ALOGD("retrieved %d scan data from interface[%d] = %p", num_scan_data, iface, handle);
    646         return scanData.detach();
    647     } else {
    648         return NULL;
    649     }
    650 }
    651 
    652 
    653 static jboolean android_net_wifi_getScanCapabilities(
    654         JNIEnv *env, jclass cls, jint iface, jobject capabilities) {
    655 
    656     JNIHelper helper(env);
    657     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
    658     // ALOGD("getting scan capabilities on interface[%d] = %p", iface, handle);
    659 
    660     wifi_gscan_capabilities c;
    661     memset(&c, 0, sizeof(c));
    662     int result = hal_fn.wifi_get_gscan_capabilities(handle, &c);
    663     if (result != WIFI_SUCCESS) {
    664         ALOGD("failed to get capabilities : %d", result);
    665         return JNI_FALSE;
    666     }
    667 
    668     helper.setIntField(capabilities, "max_scan_cache_size", c.max_scan_cache_size);
    669     helper.setIntField(capabilities, "max_scan_buckets", c.max_scan_buckets);
    670     helper.setIntField(capabilities, "max_ap_cache_per_scan", c.max_ap_cache_per_scan);
    671     helper.setIntField(capabilities, "max_rssi_sample_size", c.max_rssi_sample_size);
    672     helper.setIntField(capabilities, "max_scan_reporting_threshold", c.max_scan_reporting_threshold);
    673     helper.setIntField(capabilities, "max_hotlist_bssids", c.max_hotlist_bssids);
    674     helper.setIntField(capabilities, "max_significant_wifi_change_aps",
    675                 c.max_significant_wifi_change_aps);
    676 
    677     return JNI_TRUE;
    678 }
    679 
    680 
    681 static byte parseHexChar(char ch) {
    682     if (isdigit(ch))
    683         return ch - '0';
    684     else if ('A' <= ch && ch <= 'F')
    685         return ch - 'A' + 10;
    686     else if ('a' <= ch && ch <= 'f')
    687         return ch - 'a' + 10;
    688     else {
    689         ALOGE("invalid character in bssid %c", ch);
    690         return 0;
    691     }
    692 }
    693 
    694 static byte parseHexByte(const char * &str) {
    695     byte b = parseHexChar(str[0]);
    696     if (str[1] == ':' || str[1] == '\0') {
    697         str += 2;
    698         return b;
    699     } else {
    700         b = b << 4 | parseHexChar(str[1]);
    701         str += 3;
    702         return b;
    703     }
    704 }
    705 
    706 static void parseMacAddress(const char *str, mac_addr addr) {
    707     addr[0] = parseHexByte(str);
    708     addr[1] = parseHexByte(str);
    709     addr[2] = parseHexByte(str);
    710     addr[3] = parseHexByte(str);
    711     addr[4] = parseHexByte(str);
    712     addr[5] = parseHexByte(str);
    713 }
    714 
    715 static bool parseMacAddress(JNIEnv *env, jobject obj, mac_addr addr) {
    716     JNIHelper helper(env);
    717     JNIObject<jstring> macAddrString = helper.getStringField(obj, "bssid");
    718     if (macAddrString == NULL) {
    719         ALOGE("Error getting bssid field");
    720         return false;
    721     }
    722 
    723     ScopedUtfChars chars(env, macAddrString);
    724     const char *bssid = chars.c_str();
    725     if (bssid == NULL) {
    726         ALOGE("Error getting bssid");
    727         return false;
    728     }
    729 
    730     parseMacAddress(bssid, addr);
    731     return true;
    732 }
    733 
    734 static void onHotlistApFound(wifi_request_id id,
    735         unsigned num_results, wifi_scan_result *results) {
    736 
    737     JNIHelper helper(mVM);
    738     ALOGD("onHotlistApFound called, vm = %p, obj = %p, num_results = %d", mVM, mCls, num_results);
    739 
    740     JNIObject<jobjectArray> scanResults = helper.newObjectArray(num_results,
    741             "android/net/wifi/ScanResult", NULL);
    742     if (scanResults == NULL) {
    743         ALOGE("Error in allocating array");
    744         return;
    745     }
    746 
    747     for (unsigned i = 0; i < num_results; i++) {
    748 
    749         JNIObject<jobject> scanResult = createScanResult(helper, &results[i]);
    750         if (scanResult == NULL) {
    751             ALOGE("Error in creating scan result");
    752             return;
    753         }
    754 
    755         helper.setObjectArrayElement(scanResults, i, scanResult);
    756 
    757         ALOGD("Found AP %32s", results[i].ssid);
    758     }
    759 
    760     helper.reportEvent(mCls, "onHotlistApFound", "(I[Landroid/net/wifi/ScanResult;)V",
    761         id, scanResults.get());
    762 }
    763 
    764 static void onHotlistApLost(wifi_request_id id,
    765         unsigned num_results, wifi_scan_result *results) {
    766 
    767     JNIHelper helper(mVM);
    768     ALOGD("onHotlistApLost called, vm = %p, obj = %p, num_results = %d", mVM, mCls, num_results);
    769 
    770     JNIObject<jobjectArray> scanResults = helper.newObjectArray(num_results,
    771             "android/net/wifi/ScanResult", NULL);
    772     if (scanResults == NULL) {
    773         ALOGE("Error in allocating array");
    774         return;
    775     }
    776 
    777     for (unsigned i = 0; i < num_results; i++) {
    778 
    779         JNIObject<jobject> scanResult = createScanResult(helper, &results[i]);
    780         if (scanResult == NULL) {
    781             ALOGE("Error in creating scan result");
    782             return;
    783         }
    784 
    785         helper.setObjectArrayElement(scanResults, i, scanResult);
    786 
    787         ALOGD("Lost AP %32s", results[i].ssid);
    788     }
    789 
    790     helper.reportEvent(mCls, "onHotlistApLost", "(I[Landroid/net/wifi/ScanResult;)V",
    791         id, scanResults.get());
    792 }
    793 
    794 
    795 static jboolean android_net_wifi_setHotlist(
    796         JNIEnv *env, jclass cls, jint iface, jint id, jobject ap)  {
    797 
    798     JNIHelper helper(env);
    799     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
    800     ALOGD("setting hotlist on interface[%d] = %p", iface, handle);
    801 
    802     wifi_bssid_hotlist_params params;
    803     memset(&params, 0, sizeof(params));
    804 
    805     params.lost_ap_sample_size = helper.getIntField(ap, "apLostThreshold");
    806 
    807     JNIObject<jobjectArray> array = helper.getArrayField(
    808             ap, "bssidInfos", "[Landroid/net/wifi/WifiScanner$BssidInfo;");
    809     params.num_bssid = helper.getArrayLength(array);
    810 
    811     if (params.num_bssid == 0) {
    812         ALOGE("Error in accesing array");
    813         return false;
    814     }
    815 
    816     for (int i = 0; i < params.num_bssid; i++) {
    817         JNIObject<jobject> objAp = helper.getObjectArrayElement(array, i);
    818 
    819         JNIObject<jstring> macAddrString = helper.getStringField(objAp, "bssid");
    820         if (macAddrString == NULL) {
    821             ALOGE("Error getting bssid field");
    822             return false;
    823         }
    824 
    825         ScopedUtfChars chars(env, macAddrString);
    826         const char *bssid = chars.c_str();
    827         if (bssid == NULL) {
    828             ALOGE("Error getting bssid");
    829             return false;
    830         }
    831         parseMacAddress(bssid, params.ap[i].bssid);
    832 
    833         mac_addr addr;
    834         memcpy(addr, params.ap[i].bssid, sizeof(mac_addr));
    835 
    836         char bssidOut[32];
    837         sprintf(bssidOut, "%0x:%0x:%0x:%0x:%0x:%0x", addr[0], addr[1],
    838             addr[2], addr[3], addr[4], addr[5]);
    839 
    840         ALOGD("Added bssid %s", bssidOut);
    841 
    842         params.ap[i].low = helper.getIntField(objAp, "low");
    843         params.ap[i].high = helper.getIntField(objAp, "high");
    844     }
    845 
    846     wifi_hotlist_ap_found_handler handler;
    847     memset(&handler, 0, sizeof(handler));
    848 
    849     handler.on_hotlist_ap_found = &onHotlistApFound;
    850     handler.on_hotlist_ap_lost  = &onHotlistApLost;
    851     return hal_fn.wifi_set_bssid_hotlist(id, handle, params, handler) == WIFI_SUCCESS;
    852 }
    853 
    854 static jboolean android_net_wifi_resetHotlist(JNIEnv *env, jclass cls, jint iface, jint id)  {
    855 
    856     JNIHelper helper(env);
    857     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
    858     ALOGD("resetting hotlist on interface[%d] = %p", iface, handle);
    859 
    860     return hal_fn.wifi_reset_bssid_hotlist(id, handle) == WIFI_SUCCESS;
    861 }
    862 
    863 void onSignificantWifiChange(wifi_request_id id,
    864         unsigned num_results, wifi_significant_change_result **results) {
    865 
    866     JNIHelper helper(mVM);
    867 
    868     ALOGD("onSignificantWifiChange called, vm = %p, obj = %p", mVM, mCls);
    869 
    870     JNIObject<jobjectArray> scanResults = helper.newObjectArray(
    871             num_results, "android/net/wifi/ScanResult", NULL);
    872     if (scanResults == NULL) {
    873         ALOGE("Error in allocating array");
    874         return;
    875     }
    876 
    877     for (unsigned i = 0; i < num_results; i++) {
    878 
    879         wifi_significant_change_result &result = *(results[i]);
    880 
    881         JNIObject<jobject> scanResult = helper.createObject("android/net/wifi/ScanResult");
    882         if (scanResult == NULL) {
    883             ALOGE("Error in creating scan result");
    884             return;
    885         }
    886 
    887         // helper.setStringField(scanResult, "SSID", results[i].ssid);
    888 
    889         char bssid[32];
    890         sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result.bssid[0], result.bssid[1],
    891             result.bssid[2], result.bssid[3], result.bssid[4], result.bssid[5]);
    892 
    893         helper.setStringField(scanResult, "BSSID", bssid);
    894 
    895         helper.setIntField(scanResult, "level", result.rssi[0]);
    896         helper.setIntField(scanResult, "frequency", result.channel);
    897         // helper.setLongField(scanResult, "timestamp", result.ts);
    898 
    899         helper.setObjectArrayElement(scanResults, i, scanResult);
    900     }
    901 
    902     helper.reportEvent(mCls, "onSignificantWifiChange", "(I[Landroid/net/wifi/ScanResult;)V",
    903         id, scanResults.get());
    904 
    905 }
    906 
    907 static jboolean android_net_wifi_trackSignificantWifiChange(
    908         JNIEnv *env, jclass cls, jint iface, jint id, jobject settings)  {
    909 
    910     JNIHelper helper(env);
    911     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
    912     ALOGD("tracking significant wifi change on interface[%d] = %p", iface, handle);
    913 
    914     wifi_significant_change_params params;
    915     memset(&params, 0, sizeof(params));
    916 
    917     params.rssi_sample_size = helper.getIntField(settings, "rssiSampleSize");
    918     params.lost_ap_sample_size = helper.getIntField(settings, "lostApSampleSize");
    919     params.min_breaching = helper.getIntField(settings, "minApsBreachingThreshold");
    920 
    921     const char *bssid_info_array_type = "[Landroid/net/wifi/WifiScanner$BssidInfo;";
    922     JNIObject<jobjectArray> bssids = helper.getArrayField(
    923             settings, "bssidInfos", bssid_info_array_type);
    924     params.num_bssid = helper.getArrayLength(bssids);
    925 
    926     if (params.num_bssid == 0) {
    927         ALOGE("Error in accessing array");
    928         return false;
    929     }
    930 
    931     ALOGD("Initialized common fields %d, %d, %d, %d", params.rssi_sample_size,
    932             params.lost_ap_sample_size, params.min_breaching, params.num_bssid);
    933 
    934     for (int i = 0; i < params.num_bssid; i++) {
    935         JNIObject<jobject> objAp = helper.getObjectArrayElement(bssids, i);
    936 
    937         JNIObject<jstring> macAddrString = helper.getStringField(objAp, "bssid");
    938         if (macAddrString == NULL) {
    939             ALOGE("Error getting bssid field");
    940             return false;
    941         }
    942 
    943         ScopedUtfChars chars(env, macAddrString.get());
    944         const char *bssid = chars.c_str();
    945         if (bssid == NULL) {
    946             ALOGE("Error getting bssid");
    947             return false;
    948         }
    949 
    950         mac_addr addr;
    951         parseMacAddress(bssid, addr);
    952         memcpy(params.ap[i].bssid, addr, sizeof(mac_addr));
    953 
    954         char bssidOut[32];
    955         sprintf(bssidOut, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1],
    956             addr[2], addr[3], addr[4], addr[5]);
    957 
    958         params.ap[i].low = helper.getIntField(objAp, "low");
    959         params.ap[i].high = helper.getIntField(objAp, "high");
    960 
    961         ALOGD("Added bssid %s, [%04d, %04d]", bssidOut, params.ap[i].low, params.ap[i].high);
    962     }
    963 
    964     ALOGD("Added %d bssids", params.num_bssid);
    965 
    966     wifi_significant_change_handler handler;
    967     memset(&handler, 0, sizeof(handler));
    968 
    969     handler.on_significant_change = &onSignificantWifiChange;
    970     return hal_fn.wifi_set_significant_change_handler(id, handle, params, handler) == WIFI_SUCCESS;
    971 }
    972 
    973 static jboolean android_net_wifi_untrackSignificantWifiChange(
    974         JNIEnv *env, jclass cls, jint iface, jint id)  {
    975 
    976     JNIHelper helper(env);
    977     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
    978     ALOGD("resetting significant wifi change on interface[%d] = %p", iface, handle);
    979 
    980     return hal_fn.wifi_reset_significant_change_handler(id, handle) == WIFI_SUCCESS;
    981 }
    982 
    983 wifi_iface_stat link_stat;
    984 wifi_radio_stat radio_stat; // L release has support for only one radio
    985 
    986 void onLinkStatsResults(wifi_request_id id, wifi_iface_stat *iface_stat,
    987          int num_radios, wifi_radio_stat *radio_stats)
    988 {
    989     if (iface_stat != 0) {
    990         memcpy(&link_stat, iface_stat, sizeof(wifi_iface_stat));
    991     } else {
    992         memset(&link_stat, 0, sizeof(wifi_iface_stat));
    993     }
    994 
    995     if (num_radios > 0 && radio_stats != 0) {
    996         memcpy(&radio_stat, radio_stats, sizeof(wifi_radio_stat));
    997     } else {
    998         memset(&radio_stat, 0, sizeof(wifi_radio_stat));
    999     }
   1000 }
   1001 
   1002 static void android_net_wifi_setLinkLayerStats (JNIEnv *env, jclass cls, jint iface, int enable)  {
   1003     JNIHelper helper(env);
   1004     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1005 
   1006     wifi_link_layer_params params;
   1007     params.aggressive_statistics_gathering = enable;
   1008     params.mpdu_size_threshold = 128;
   1009 
   1010     ALOGD("android_net_wifi_setLinkLayerStats: %u\n", enable);
   1011 
   1012     hal_fn.wifi_set_link_stats(handle, params);
   1013 }
   1014 
   1015 static jobject android_net_wifi_getLinkLayerStats (JNIEnv *env, jclass cls, jint iface)  {
   1016 
   1017     JNIHelper helper(env);
   1018     wifi_stats_result_handler handler;
   1019     memset(&handler, 0, sizeof(handler));
   1020     handler.on_link_stats_results = &onLinkStatsResults;
   1021     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1022     int result = hal_fn.wifi_get_link_stats(0, handle, handler);
   1023     if (result < 0) {
   1024         ALOGE("android_net_wifi_getLinkLayerStats: failed to get link statistics\n");
   1025         return NULL;
   1026     }
   1027 
   1028     JNIObject<jobject> wifiLinkLayerStats = helper.createObject(
   1029             "android/net/wifi/WifiLinkLayerStats");
   1030     if (wifiLinkLayerStats == NULL) {
   1031        ALOGE("Error in allocating wifiLinkLayerStats");
   1032        return NULL;
   1033     }
   1034 
   1035     helper.setIntField(wifiLinkLayerStats, "beacon_rx", link_stat.beacon_rx);
   1036     helper.setIntField(wifiLinkLayerStats, "rssi_mgmt", link_stat.rssi_mgmt);
   1037     helper.setLongField(wifiLinkLayerStats, "rxmpdu_be", link_stat.ac[WIFI_AC_BE].rx_mpdu);
   1038     helper.setLongField(wifiLinkLayerStats, "rxmpdu_bk", link_stat.ac[WIFI_AC_BK].rx_mpdu);
   1039     helper.setLongField(wifiLinkLayerStats, "rxmpdu_vi", link_stat.ac[WIFI_AC_VI].rx_mpdu);
   1040     helper.setLongField(wifiLinkLayerStats, "rxmpdu_vo", link_stat.ac[WIFI_AC_VO].rx_mpdu);
   1041     helper.setLongField(wifiLinkLayerStats, "txmpdu_be", link_stat.ac[WIFI_AC_BE].tx_mpdu);
   1042     helper.setLongField(wifiLinkLayerStats, "txmpdu_bk", link_stat.ac[WIFI_AC_BK].tx_mpdu);
   1043     helper.setLongField(wifiLinkLayerStats, "txmpdu_vi", link_stat.ac[WIFI_AC_VI].tx_mpdu);
   1044     helper.setLongField(wifiLinkLayerStats, "txmpdu_vo", link_stat.ac[WIFI_AC_VO].tx_mpdu);
   1045     helper.setLongField(wifiLinkLayerStats, "lostmpdu_be", link_stat.ac[WIFI_AC_BE].mpdu_lost);
   1046     helper.setLongField(wifiLinkLayerStats, "lostmpdu_bk", link_stat.ac[WIFI_AC_BK].mpdu_lost);
   1047     helper.setLongField(wifiLinkLayerStats, "lostmpdu_vi",  link_stat.ac[WIFI_AC_VI].mpdu_lost);
   1048     helper.setLongField(wifiLinkLayerStats, "lostmpdu_vo", link_stat.ac[WIFI_AC_VO].mpdu_lost);
   1049     helper.setLongField(wifiLinkLayerStats, "retries_be", link_stat.ac[WIFI_AC_BE].retries);
   1050     helper.setLongField(wifiLinkLayerStats, "retries_bk", link_stat.ac[WIFI_AC_BK].retries);
   1051     helper.setLongField(wifiLinkLayerStats, "retries_vi", link_stat.ac[WIFI_AC_VI].retries);
   1052     helper.setLongField(wifiLinkLayerStats, "retries_vo", link_stat.ac[WIFI_AC_VO].retries);
   1053 
   1054     helper.setIntField(wifiLinkLayerStats, "on_time", radio_stat.on_time);
   1055     helper.setIntField(wifiLinkLayerStats, "tx_time", radio_stat.tx_time);
   1056     helper.setIntField(wifiLinkLayerStats, "rx_time", radio_stat.rx_time);
   1057     helper.setIntField(wifiLinkLayerStats, "on_time_scan", radio_stat.on_time_scan);
   1058 
   1059     return wifiLinkLayerStats.detach();
   1060 }
   1061 
   1062 static jint android_net_wifi_getSupportedFeatures(JNIEnv *env, jclass cls, jint iface) {
   1063 
   1064     JNIHelper helper(env);
   1065     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1066     feature_set set = 0;
   1067 
   1068     wifi_error result = WIFI_SUCCESS;
   1069     /*
   1070     set = WIFI_FEATURE_INFRA
   1071         | WIFI_FEATURE_INFRA_5G
   1072         | WIFI_FEATURE_HOTSPOT
   1073         | WIFI_FEATURE_P2P
   1074         | WIFI_FEATURE_SOFT_AP
   1075         | WIFI_FEATURE_GSCAN
   1076         | WIFI_FEATURE_PNO
   1077         | WIFI_FEATURE_TDLS
   1078         | WIFI_FEATURE_EPR;
   1079     */
   1080 
   1081     result = hal_fn.wifi_get_supported_feature_set(handle, &set);
   1082     if (result == WIFI_SUCCESS) {
   1083         // ALOGD("wifi_get_supported_feature_set returned set = 0x%x", set);
   1084         return set;
   1085     } else {
   1086         ALOGE("wifi_get_supported_feature_set returned error = 0x%x", result);
   1087         return 0;
   1088     }
   1089 }
   1090 
   1091 static void onRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* results[]) {
   1092 
   1093     JNIHelper helper(mVM);
   1094 
   1095     ALOGD("onRttResults called, vm = %p, obj = %p", mVM, mCls);
   1096 
   1097     JNIObject<jobjectArray> rttResults = helper.newObjectArray(
   1098             num_results, "android/net/wifi/RttManager$RttResult", NULL);
   1099     if (rttResults == NULL) {
   1100         ALOGE("Error in allocating array");
   1101         return;
   1102     }
   1103 
   1104     for (unsigned i = 0; i < num_results; i++) {
   1105 
   1106         wifi_rtt_result *result = results[i];
   1107 
   1108         JNIObject<jobject> rttResult = helper.createObject("android/net/wifi/RttManager$RttResult");
   1109         if (rttResult == NULL) {
   1110             ALOGE("Error in creating rtt result");
   1111             return;
   1112         }
   1113 
   1114         char bssid[32];
   1115         sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result->addr[0], result->addr[1],
   1116             result->addr[2], result->addr[3], result->addr[4], result->addr[5]);
   1117 
   1118         helper.setStringField(rttResult, "bssid", bssid);
   1119         helper.setIntField( rttResult, "burstNumber",              result->burst_num);
   1120         helper.setIntField( rttResult, "measurementFrameNumber",   result->measurement_number);
   1121         helper.setIntField( rttResult, "successMeasurementFrameNumber",   result->success_number);
   1122         helper.setIntField(rttResult, "frameNumberPerBurstPeer",   result->number_per_burst_peer);
   1123         helper.setIntField( rttResult, "status",                   result->status);
   1124         helper.setIntField( rttResult, "measurementType",          result->type);
   1125         helper.setIntField(rttResult, "retryAfterDuration",       result->retry_after_duration);
   1126         helper.setLongField(rttResult, "ts",                       result->ts);
   1127         helper.setIntField( rttResult, "rssi",                     result->rssi);
   1128         helper.setIntField( rttResult, "rssiSpread",               result->rssi_spread);
   1129         helper.setIntField( rttResult, "txRate",                   result->tx_rate.bitrate);
   1130         helper.setIntField( rttResult, "rxRate",                   result->rx_rate.bitrate);
   1131         helper.setLongField(rttResult, "rtt",                      result->rtt);
   1132         helper.setLongField(rttResult, "rttStandardDeviation",     result->rtt_sd);
   1133         helper.setIntField( rttResult, "distance",                 result->distance);
   1134         helper.setIntField( rttResult, "distanceStandardDeviation", result->distance_sd);
   1135         helper.setIntField( rttResult, "distanceSpread",           result->distance_spread);
   1136         helper.setIntField( rttResult, "burstDuration",             result->burst_duration);
   1137         helper.setIntField( rttResult, "negotiatedBurstNum",      result->negotiated_burst_num);
   1138 
   1139         JNIObject<jobject> LCI = helper.createObject(
   1140                 "android/net/wifi/RttManager$WifiInformationElement");
   1141         if (result->LCI != NULL && result->LCI->len > 0) {
   1142             ALOGD("Add LCI in result");
   1143             helper.setByteField(LCI, "id", result->LCI->id);
   1144             JNIObject<jbyteArray> elements = helper.newByteArray(result->LCI->len);
   1145             jbyte *bytes = (jbyte *)&(result->LCI->data[0]);
   1146             helper.setByteArrayRegion(elements, 0, result->LCI->len, bytes);
   1147             helper.setObjectField(LCI, "data", "[B", elements);
   1148         } else {
   1149             ALOGD("No LCI in result");
   1150             helper.setByteField(LCI, "id", (byte)(0xff));
   1151         }
   1152         helper.setObjectField(rttResult, "LCI",
   1153             "Landroid/net/wifi/RttManager$WifiInformationElement;", LCI);
   1154 
   1155         JNIObject<jobject> LCR = helper.createObject(
   1156                 "android/net/wifi/RttManager$WifiInformationElement");
   1157         if (result->LCR != NULL && result->LCR->len > 0) {
   1158             ALOGD("Add LCR in result");
   1159             helper.setByteField(LCR, "id",           result->LCR->id);
   1160             JNIObject<jbyteArray> elements = helper.newByteArray(result->LCI->len);
   1161             jbyte *bytes = (jbyte *)&(result->LCR->data[0]);
   1162             helper.setByteArrayRegion(elements, 0, result->LCI->len, bytes);
   1163             helper.setObjectField(LCR, "data", "[B", elements);
   1164         } else {
   1165             ALOGD("No LCR in result");
   1166             helper.setByteField(LCR, "id", (byte)(0xff));
   1167         }
   1168         helper.setObjectField(rttResult, "LCR",
   1169             "Landroid/net/wifi/RttManager$WifiInformationElement;", LCR);
   1170 
   1171         helper.setObjectArrayElement(rttResults, i, rttResult);
   1172     }
   1173 
   1174     helper.reportEvent(mCls, "onRttResults", "(I[Landroid/net/wifi/RttManager$RttResult;)V",
   1175         id, rttResults.get());
   1176 }
   1177 
   1178 const int MaxRttConfigs = 16;
   1179 
   1180 static jboolean android_net_wifi_requestRange(
   1181         JNIEnv *env, jclass cls, jint iface, jint id, jobject params)  {
   1182 
   1183     JNIHelper helper(env);
   1184 
   1185     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1186     ALOGD("sending rtt request [%d] = %p", id, handle);
   1187 
   1188     wifi_rtt_config configs[MaxRttConfigs];
   1189     memset(&configs, 0, sizeof(configs));
   1190 
   1191     int len = helper.getArrayLength((jobjectArray)params);
   1192     if (len > MaxRttConfigs) {
   1193         return false;
   1194     }
   1195 
   1196     for (int i = 0; i < len; i++) {
   1197 
   1198         JNIObject<jobject> param = helper.getObjectArrayElement((jobjectArray)params, i);
   1199         if (param == NULL) {
   1200             ALOGD("could not get element %d", i);
   1201             continue;
   1202         }
   1203 
   1204         wifi_rtt_config &config = configs[i];
   1205 
   1206         parseMacAddress(env, param, config.addr);
   1207         config.type = (wifi_rtt_type)helper.getIntField(param, "requestType");
   1208         config.peer = (rtt_peer_type)helper.getIntField(param, "deviceType");
   1209         config.channel.center_freq = helper.getIntField(param, "frequency");
   1210         config.channel.width = (wifi_channel_width) helper.getIntField(param, "channelWidth");
   1211         config.channel.center_freq0 = helper.getIntField(param, "centerFreq0");
   1212         config.channel.center_freq1 = helper.getIntField(param, "centerFreq1");
   1213 
   1214         config.num_burst = helper.getIntField(param, "numberBurst");
   1215         config.burst_period = (unsigned) helper.getIntField(param, "interval");
   1216         config.num_frames_per_burst = (unsigned) helper.getIntField(param, "numSamplesPerBurst");
   1217         config.num_retries_per_rtt_frame = (unsigned) helper.getIntField(param,
   1218                 "numRetriesPerMeasurementFrame");
   1219         config.num_retries_per_ftmr = (unsigned) helper.getIntField(param, "numRetriesPerFTMR");
   1220         config.LCI_request = helper.getBoolField(param, "LCIRequest") ? 1 : 0;
   1221         config.LCR_request = helper.getBoolField(param, "LCRRequest") ? 1 : 0;
   1222         config.burst_duration = (unsigned) helper.getIntField(param, "burstTimeout");
   1223         config.preamble = (wifi_rtt_preamble) helper.getIntField(param, "preamble");
   1224         config.bw = (wifi_rtt_bw) helper.getIntField(param, "bandwidth");
   1225 
   1226         ALOGD("RTT request destination %d: type is %d, peer is %d, bw is %d, center_freq is %d ", i,
   1227                 config.type,config.peer, config.channel.width,  config.channel.center_freq);
   1228         ALOGD("center_freq0 is %d, center_freq1 is %d, num_burst is %d,interval is %d",
   1229                 config.channel.center_freq0, config.channel.center_freq1, config.num_burst,
   1230                 config.burst_period);
   1231         ALOGD("frames_per_burst is %d, retries of measurement frame is %d, retries_per_ftmr is %d",
   1232                 config.num_frames_per_burst, config.num_retries_per_rtt_frame,
   1233                 config.num_retries_per_ftmr);
   1234         ALOGD("LCI_requestis %d, LCR_request is %d,  burst_timeout is %d, preamble is %d, bw is %d",
   1235                 config.LCI_request, config.LCR_request, config.burst_duration, config.preamble,
   1236                 config.bw);
   1237     }
   1238 
   1239     wifi_rtt_event_handler handler;
   1240     handler.on_rtt_results = &onRttResults;
   1241 
   1242     return hal_fn.wifi_rtt_range_request(id, handle, len, configs, handler) == WIFI_SUCCESS;
   1243 }
   1244 
   1245 static jboolean android_net_wifi_cancelRange(
   1246         JNIEnv *env, jclass cls, jint iface, jint id, jobject params)  {
   1247 
   1248     JNIHelper helper(env);
   1249     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1250     ALOGD("cancelling rtt request [%d] = %p", id, handle);
   1251 
   1252     mac_addr addrs[MaxRttConfigs];
   1253     memset(&addrs, 0, sizeof(addrs));
   1254 
   1255     int len = helper.getArrayLength((jobjectArray)params);
   1256     if (len > MaxRttConfigs) {
   1257         return false;
   1258     }
   1259 
   1260     for (int i = 0; i < len; i++) {
   1261 
   1262         JNIObject<jobject> param = helper.getObjectArrayElement(params, i);
   1263         if (param == NULL) {
   1264             ALOGD("could not get element %d", i);
   1265             continue;
   1266         }
   1267 
   1268         parseMacAddress(env, param, addrs[i]);
   1269     }
   1270 
   1271     return hal_fn.wifi_rtt_range_cancel(id, handle, len, addrs) == WIFI_SUCCESS;
   1272 }
   1273 
   1274 static jboolean android_net_wifi_setScanningMacOui(JNIEnv *env, jclass cls,
   1275         jint iface, jbyteArray param)  {
   1276 
   1277     JNIHelper helper(env);
   1278     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1279     ALOGD("setting scan oui %p", handle);
   1280 
   1281     static const unsigned oui_len = 3;          /* OUI is upper 3 bytes of mac_address */
   1282     int len = helper.getArrayLength(param);
   1283     if (len != oui_len) {
   1284         ALOGE("invalid oui length %d", len);
   1285         return false;
   1286     }
   1287 
   1288     ScopedBytesRO paramBytes(env, param);
   1289     const jbyte* bytes = paramBytes.get();
   1290     if (bytes == NULL) {
   1291         ALOGE("failed to get array");
   1292         return false;
   1293     }
   1294 
   1295     return hal_fn.wifi_set_scanning_mac_oui(handle, (byte *)bytes) == WIFI_SUCCESS;
   1296 }
   1297 
   1298 static jboolean android_net_wifi_is_get_channels_for_band_supported(JNIEnv *env, jclass cls){
   1299     return (hal_fn.wifi_get_valid_channels == wifi_get_valid_channels_stub);
   1300 }
   1301 
   1302 static jintArray android_net_wifi_getValidChannels(JNIEnv *env, jclass cls,
   1303         jint iface, jint band)  {
   1304 
   1305     JNIHelper helper(env);
   1306     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1307     ALOGD("getting valid channels %p", handle);
   1308 
   1309     static const int MaxChannels = 64;
   1310     wifi_channel channels[64];
   1311     int num_channels = 0;
   1312     wifi_error result = hal_fn.wifi_get_valid_channels(handle, band, MaxChannels,
   1313             channels, &num_channels);
   1314 
   1315     if (result == WIFI_SUCCESS) {
   1316         JNIObject<jintArray> channelArray = helper.newIntArray(num_channels);
   1317         if (channelArray == NULL) {
   1318             ALOGE("failed to allocate channel list");
   1319             return NULL;
   1320         }
   1321 
   1322         helper.setIntArrayRegion(channelArray, 0, num_channels, channels);
   1323         return channelArray.detach();
   1324     } else {
   1325         ALOGE("failed to get channel list : %d", result);
   1326         return NULL;
   1327     }
   1328 }
   1329 
   1330 static jboolean android_net_wifi_setDfsFlag(JNIEnv *env, jclass cls, jint iface, jboolean dfs) {
   1331 
   1332     JNIHelper helper(env);
   1333     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1334     ALOGD("setting dfs flag to %s, %p", dfs ? "true" : "false", handle);
   1335 
   1336     u32 nodfs = dfs ? 0 : 1;
   1337     wifi_error result = hal_fn.wifi_set_nodfs_flag(handle, nodfs);
   1338     return result == WIFI_SUCCESS;
   1339 }
   1340 
   1341 static jobject android_net_wifi_get_rtt_capabilities(JNIEnv *env, jclass cls, jint iface) {
   1342 
   1343     JNIHelper helper(env);
   1344     wifi_rtt_capabilities rtt_capabilities;
   1345     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1346     wifi_error ret = hal_fn.wifi_get_rtt_capabilities(handle, &rtt_capabilities);
   1347 
   1348     if(WIFI_SUCCESS == ret) {
   1349          JNIObject<jobject> capabilities = helper.createObject(
   1350                 "android/net/wifi/RttManager$RttCapabilities");
   1351          helper.setBooleanField(capabilities, "oneSidedRttSupported",
   1352                  rtt_capabilities.rtt_one_sided_supported == 1);
   1353          helper.setBooleanField(capabilities, "twoSided11McRttSupported",
   1354                  rtt_capabilities.rtt_ftm_supported == 1);
   1355          helper.setBooleanField(capabilities, "lciSupported",
   1356                  rtt_capabilities.lci_support);
   1357          helper.setBooleanField(capabilities, "lcrSupported",
   1358                  rtt_capabilities.lcr_support);
   1359          helper.setIntField(capabilities, "preambleSupported",
   1360                  rtt_capabilities.preamble_support);
   1361          helper.setIntField(capabilities, "bwSupported",
   1362                  rtt_capabilities.bw_support);
   1363          ALOGD("One side RTT is: %s", rtt_capabilities.rtt_one_sided_supported ==1 ? "support" :
   1364                  "not support");
   1365          ALOGD("Two side RTT is: %s", rtt_capabilities.rtt_ftm_supported == 1 ? "support" :
   1366                  "not support");
   1367          ALOGD("LCR is: %s", rtt_capabilities.lcr_support == 1 ? "support" : "not support");
   1368 
   1369          ALOGD("LCI is: %s", rtt_capabilities.lci_support == 1 ? "support" : "not support");
   1370 
   1371          ALOGD("Support Preamble is : %d support BW is %d", rtt_capabilities.preamble_support,
   1372                  rtt_capabilities.bw_support);
   1373          return capabilities.detach();
   1374     } else {
   1375         return NULL;
   1376     }
   1377 }
   1378 
   1379 static jboolean android_net_wifi_set_Country_Code_Hal(JNIEnv *env,jclass cls, jint iface,
   1380         jstring country_code) {
   1381 
   1382     JNIHelper helper(env);
   1383     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1384 
   1385     ScopedUtfChars chars(env, country_code);
   1386     const char *country = chars.c_str();
   1387 
   1388     ALOGD("set country code: %s", country);
   1389     wifi_error res = hal_fn.wifi_set_country_code(handle, country);
   1390     return res == WIFI_SUCCESS;
   1391 }
   1392 
   1393 static jboolean android_net_wifi_enable_disable_tdls(JNIEnv *env,jclass cls, jint iface,
   1394         jboolean enable, jstring addr) {
   1395 
   1396     JNIHelper helper(env);
   1397     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1398 
   1399     mac_addr address;
   1400     parseMacAddress(env, addr, address);
   1401     wifi_tdls_handler tdls_handler;
   1402     //tdls_handler.on_tdls_state_changed = &on_tdls_state_changed;
   1403 
   1404     if(enable) {
   1405         return (hal_fn.wifi_enable_tdls(handle, address, NULL, tdls_handler) == WIFI_SUCCESS);
   1406     } else {
   1407         return (hal_fn.wifi_disable_tdls(handle, address) == WIFI_SUCCESS);
   1408     }
   1409 }
   1410 
   1411 static void on_tdls_state_changed(mac_addr addr, wifi_tdls_status status) {
   1412 
   1413     JNIHelper helper(mVM);
   1414 
   1415     ALOGD("on_tdls_state_changed is called: vm = %p, obj = %p", mVM, mCls);
   1416 
   1417     char mac[32];
   1418     sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4],
   1419             addr[5]);
   1420 
   1421     JNIObject<jstring> mac_address = helper.newStringUTF(mac);
   1422     helper.reportEvent(mCls, "onTdlsStatus", "(Ljava/lang/StringII;)V",
   1423         mac_address.get(), status.state, status.reason);
   1424 
   1425 }
   1426 
   1427 static jobject android_net_wifi_get_tdls_status(JNIEnv *env,jclass cls, jint iface,jstring addr) {
   1428 
   1429     JNIHelper helper(env);
   1430     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1431 
   1432     mac_addr address;
   1433     parseMacAddress(env, addr, address);
   1434 
   1435     wifi_tdls_status status;
   1436 
   1437     wifi_error ret;
   1438     ret = hal_fn.wifi_get_tdls_status(handle, address, &status );
   1439 
   1440     if (ret != WIFI_SUCCESS) {
   1441         return NULL;
   1442     } else {
   1443         JNIObject<jobject> tdls_status = helper.createObject(
   1444                 "com/android/server/wifi/WifiNative$TdlsStatus");
   1445         helper.setIntField(tdls_status, "channel", status.channel);
   1446         helper.setIntField(tdls_status, "global_operating_class", status.global_operating_class);
   1447         helper.setIntField(tdls_status, "state", status.state);
   1448         helper.setIntField(tdls_status, "reason", status.reason);
   1449         return tdls_status.detach();
   1450     }
   1451 }
   1452 
   1453 static jobject android_net_wifi_get_tdls_capabilities(JNIEnv *env, jclass cls, jint iface) {
   1454 
   1455     JNIHelper helper(env);
   1456     wifi_tdls_capabilities tdls_capabilities;
   1457     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1458     wifi_error ret = hal_fn.wifi_get_tdls_capabilities(handle, &tdls_capabilities);
   1459 
   1460     if (WIFI_SUCCESS == ret) {
   1461          JNIObject<jobject> capabilities = helper.createObject(
   1462                  "com/android/server/wifi/WifiNative$TdlsCapabilities");
   1463          helper.setIntField(capabilities, "maxConcurrentTdlsSessionNumber",
   1464                  tdls_capabilities.max_concurrent_tdls_session_num);
   1465          helper.setBooleanField(capabilities, "isGlobalTdlsSupported",
   1466                  tdls_capabilities.is_global_tdls_supported == 1);
   1467          helper.setBooleanField(capabilities, "isPerMacTdlsSupported",
   1468                  tdls_capabilities.is_per_mac_tdls_supported == 1);
   1469          helper.setBooleanField(capabilities, "isOffChannelTdlsSupported",
   1470                  tdls_capabilities.is_off_channel_tdls_supported);
   1471 
   1472          ALOGD("TDLS Max Concurrent Tdls Session Number is: %d",
   1473                  tdls_capabilities.max_concurrent_tdls_session_num);
   1474          ALOGD("Global Tdls is: %s", tdls_capabilities.is_global_tdls_supported == 1 ? "support" :
   1475                  "not support");
   1476          ALOGD("Per Mac Tdls is: %s", tdls_capabilities.is_per_mac_tdls_supported == 1 ? "support" :
   1477                  "not support");
   1478          ALOGD("Off Channel Tdls is: %s", tdls_capabilities.is_off_channel_tdls_supported == 1 ?
   1479                  "support" : "not support");
   1480 
   1481          return capabilities.detach();
   1482     } else {
   1483         return NULL;
   1484     }
   1485 }
   1486 
   1487 // ----------------------------------------------------------------------------
   1488 // Debug framework
   1489 // ----------------------------------------------------------------------------
   1490 static jint android_net_wifi_get_supported_logger_feature(JNIEnv *env, jclass cls, jint iface){
   1491     //Not implemented yet
   1492     JNIHelper helper(env);
   1493     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1494     return -1;
   1495 }
   1496 
   1497 static jobject android_net_wifi_get_driver_version(JNIEnv *env, jclass cls, jint iface) {
   1498      //Need to be fixed. The memory should be allocated from lower layer
   1499     //char *buffer = NULL;
   1500     JNIHelper helper(env);
   1501     int buffer_length =  256;
   1502     char *buffer = (char *)malloc(buffer_length);
   1503     if (!buffer) return NULL;
   1504     memset(buffer, 0, buffer_length);
   1505     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1506 
   1507     ALOGD("android_net_wifi_get_driver_version = %p", handle);
   1508 
   1509     if (handle == 0) {
   1510         return NULL;
   1511     }
   1512 
   1513     wifi_error result = hal_fn.wifi_get_driver_version(handle, buffer, buffer_length);
   1514 
   1515     if (result == WIFI_SUCCESS) {
   1516         ALOGD("buffer is %p, length is %d", buffer, buffer_length);
   1517         JNIObject<jstring> driver_version = helper.newStringUTF(buffer);
   1518         free(buffer);
   1519         return driver_version.detach();
   1520     } else {
   1521         ALOGD("Fail to get driver version");
   1522         free(buffer);
   1523         return NULL;
   1524     }
   1525 }
   1526 
   1527 static jobject android_net_wifi_get_firmware_version(JNIEnv *env, jclass cls, jint iface) {
   1528 
   1529     //char *buffer = NULL;
   1530     JNIHelper helper(env);
   1531     int buffer_length = 256;
   1532     char *buffer = (char *)malloc(buffer_length);
   1533     if (!buffer) return NULL;
   1534     memset(buffer, 0, buffer_length);
   1535     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1536 
   1537     ALOGD("android_net_wifi_get_firmware_version = %p", handle);
   1538 
   1539     if (handle == 0) {
   1540         return NULL;
   1541     }
   1542 
   1543     wifi_error result = hal_fn.wifi_get_firmware_version(handle, buffer, buffer_length);
   1544 
   1545     if (result == WIFI_SUCCESS) {
   1546         ALOGD("buffer is %p, length is %d", buffer, buffer_length);
   1547         JNIObject<jstring> firmware_version = helper.newStringUTF(buffer);
   1548         free(buffer);
   1549         return firmware_version.detach();
   1550     } else {
   1551         ALOGD("Fail to get Firmware version");
   1552         free(buffer);
   1553         return NULL;
   1554     }
   1555 }
   1556 
   1557 static jobject android_net_wifi_get_ring_buffer_status (JNIEnv *env, jclass cls, jint iface) {
   1558 
   1559     JNIHelper helper(env);
   1560     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1561 
   1562     ALOGD("android_net_wifi_get_ring_buffer_status = %p", handle);
   1563 
   1564     if (handle == 0) {
   1565         return NULL;
   1566     }
   1567 
   1568     //wifi_ring_buffer_status *status = NULL;
   1569     u32 num_rings = 10;
   1570     wifi_ring_buffer_status *status =
   1571         (wifi_ring_buffer_status *)malloc(sizeof(wifi_ring_buffer_status) * num_rings);
   1572     if (!status) return NULL;
   1573     memset(status, 0, sizeof(wifi_ring_buffer_status) * num_rings);
   1574     wifi_error result = hal_fn.wifi_get_ring_buffers_status(handle, &num_rings, status);
   1575     if (result == WIFI_SUCCESS) {
   1576         ALOGD("status is %p, number is %d", status, num_rings);
   1577 
   1578         JNIObject<jobjectArray> ringBuffersStatus = helper.newObjectArray(
   1579             num_rings, "com/android/server/wifi/WifiNative$RingBufferStatus", NULL);
   1580 
   1581         wifi_ring_buffer_status *tmp = status;
   1582 
   1583         for(u32 i = 0; i < num_rings; i++, tmp++) {
   1584 
   1585             JNIObject<jobject> ringStatus = helper.createObject(
   1586                     "com/android/server/wifi/WifiNative$RingBufferStatus");
   1587 
   1588             if (ringStatus == NULL) {
   1589                 ALOGE("Error in creating ringBufferStatus");
   1590                 free(status);
   1591                 return NULL;
   1592             }
   1593 
   1594             char name[32];
   1595             for(int j = 0; j < 32; j++) {
   1596                 name[j] = tmp->name[j];
   1597             }
   1598 
   1599             helper.setStringField(ringStatus, "name", name);
   1600             helper.setIntField(ringStatus, "flag", tmp->flags);
   1601             helper.setIntField(ringStatus, "ringBufferId", tmp->ring_id);
   1602             helper.setIntField(ringStatus, "ringBufferByteSize", tmp->ring_buffer_byte_size);
   1603             helper.setIntField(ringStatus, "verboseLevel", tmp->verbose_level);
   1604             helper.setIntField(ringStatus, "writtenBytes", tmp->written_bytes);
   1605             helper.setIntField(ringStatus, "readBytes", tmp->read_bytes);
   1606             helper.setIntField(ringStatus, "writtenRecords", tmp->written_records);
   1607 
   1608             helper.setObjectArrayElement(ringBuffersStatus, i, ringStatus);
   1609         }
   1610 
   1611         free(status);
   1612         return ringBuffersStatus.detach();
   1613     } else {
   1614         free(status);
   1615         return NULL;
   1616     }
   1617 }
   1618 
   1619 static void on_ring_buffer_data(char *ring_name, char *buffer, int buffer_size,
   1620         wifi_ring_buffer_status *status) {
   1621 
   1622     if (!ring_name || !buffer || !status ||
   1623             (unsigned int)buffer_size <= sizeof(wifi_ring_buffer_entry)) {
   1624         ALOGE("Error input for on_ring_buffer_data!");
   1625         return;
   1626     }
   1627 
   1628 
   1629     JNIHelper helper(mVM);
   1630     /* ALOGD("on_ring_buffer_data called, vm = %p, obj = %p, env = %p buffer size = %d", mVM,
   1631             mCls, env, buffer_size); */
   1632 
   1633     JNIObject<jobject> ringStatus = helper.createObject(
   1634                     "com/android/server/wifi/WifiNative$RingBufferStatus");
   1635     if (status == NULL) {
   1636         ALOGE("Error in creating ringBufferStatus");
   1637         return;
   1638     }
   1639 
   1640     helper.setStringField(ringStatus, "name", ring_name);
   1641     helper.setIntField(ringStatus, "flag", status->flags);
   1642     helper.setIntField(ringStatus, "ringBufferId", status->ring_id);
   1643     helper.setIntField(ringStatus, "ringBufferByteSize", status->ring_buffer_byte_size);
   1644     helper.setIntField(ringStatus, "verboseLevel", status->verbose_level);
   1645     helper.setIntField(ringStatus, "writtenBytes", status->written_bytes);
   1646     helper.setIntField(ringStatus, "readBytes", status->read_bytes);
   1647     helper.setIntField(ringStatus, "writtenRecords", status->written_records);
   1648 
   1649     JNIObject<jbyteArray> bytes = helper.newByteArray(buffer_size);
   1650     helper.setByteArrayRegion(bytes, 0, buffer_size, (jbyte*)buffer);
   1651 
   1652     helper.reportEvent(mCls,"onRingBufferData",
   1653             "(Lcom/android/server/wifi/WifiNative$RingBufferStatus;[B)V",
   1654             ringStatus.get(), bytes.get());
   1655 }
   1656 
   1657 static void on_alert_data(wifi_request_id id, char *buffer, int buffer_size, int err_code){
   1658 
   1659     JNIHelper helper(mVM);
   1660     ALOGD("on_alert_data called, vm = %p, obj = %p, buffer_size = %d, error code = %d"
   1661             , mVM, mCls, buffer_size, err_code);
   1662 
   1663     if (buffer_size > 0) {
   1664         JNIObject<jbyteArray> records = helper.newByteArray(buffer_size);
   1665         jbyte *bytes = (jbyte *) buffer;
   1666         helper.setByteArrayRegion(records, 0,buffer_size, bytes);
   1667         helper.reportEvent(mCls,"onWifiAlert","([BI)V", records.get(), err_code);
   1668     } else {
   1669         helper.reportEvent(mCls,"onWifiAlert","([BI)V", NULL, err_code);
   1670     }
   1671 }
   1672 
   1673 
   1674 static jboolean android_net_wifi_start_logging_ring_buffer(JNIEnv *env, jclass cls, jint iface,
   1675         jint verbose_level,jint flags, jint max_interval,jint min_data_size, jstring ring_name) {
   1676 
   1677     JNIHelper helper(env);
   1678     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1679 
   1680     ALOGD("android_net_wifi_start_logging_ring_buffer = %p", handle);
   1681 
   1682     if (handle == 0) {
   1683         return false;
   1684     }
   1685 
   1686     ScopedUtfChars chars(env, ring_name);
   1687     const char* ring_name_const_char = chars.c_str();
   1688     int ret = hal_fn.wifi_start_logging(handle, verbose_level,
   1689             flags, max_interval, min_data_size, const_cast<char *>(ring_name_const_char));
   1690 
   1691     if (ret != WIFI_SUCCESS) {
   1692         ALOGE("Fail to start logging for ring %s", ring_name_const_char);
   1693     } else {
   1694         ALOGD("start logging for ring %s", ring_name_const_char);
   1695     }
   1696 
   1697     return ret == WIFI_SUCCESS;
   1698 }
   1699 
   1700 static jboolean android_net_wifi_get_ring_buffer_data(JNIEnv *env, jclass cls, jint iface,
   1701         jstring ring_name) {
   1702 
   1703     JNIHelper helper(env);
   1704     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1705     // ALOGD("android_net_wifi_get_ring_buffer_data = %p", handle);
   1706 
   1707     ScopedUtfChars chars(env, ring_name);
   1708     const char* ring_name_const_char = chars.c_str();
   1709     int result = hal_fn.wifi_get_ring_data(handle, const_cast<char *>(ring_name_const_char));
   1710     return result == WIFI_SUCCESS;
   1711 }
   1712 
   1713 
   1714 void on_firmware_memory_dump(char *buffer, int buffer_size) {
   1715 
   1716     JNIHelper helper(mVM);
   1717     /* ALOGD("on_firmware_memory_dump called, vm = %p, obj = %p, env = %p buffer_size = %d"
   1718             , mVM, mCls, env, buffer_size); */
   1719 
   1720     if (buffer_size > 0) {
   1721         JNIObject<jbyteArray> dump = helper.newByteArray(buffer_size);
   1722         jbyte *bytes = (jbyte *) (buffer);
   1723         helper.setByteArrayRegion(dump, 0, buffer_size, bytes);
   1724         helper.reportEvent(mCls,"onWifiFwMemoryAvailable","([B)V", dump.get());
   1725     }
   1726 }
   1727 
   1728 static jboolean android_net_wifi_get_fw_memory_dump(JNIEnv *env, jclass cls, jint iface){
   1729 
   1730     JNIHelper helper(env);
   1731     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1732     // ALOGD("android_net_wifi_get_fw_memory_dump = %p", handle);
   1733 
   1734     if (handle == NULL) {
   1735         ALOGE("Can not get wifi_interface_handle");
   1736         return false;
   1737     }
   1738 
   1739     wifi_firmware_memory_dump_handler fw_dump_handle;
   1740     fw_dump_handle.on_firmware_memory_dump = on_firmware_memory_dump;
   1741     int result = hal_fn.wifi_get_firmware_memory_dump(handle, fw_dump_handle);
   1742     return result == WIFI_SUCCESS;
   1743 
   1744 }
   1745 
   1746 static jboolean android_net_wifi_set_log_handler(JNIEnv *env, jclass cls, jint iface, jint id) {
   1747 
   1748     JNIHelper helper(env);
   1749     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1750     ALOGD("android_net_wifi_set_log_handler = %p", handle);
   1751 
   1752     //initialize the handler on first time
   1753     wifi_ring_buffer_data_handler handler;
   1754     handler.on_ring_buffer_data = &on_ring_buffer_data;
   1755     int result = hal_fn.wifi_set_log_handler(id, handle, handler);
   1756     if (result != WIFI_SUCCESS) {
   1757         ALOGE("Fail to set logging handler");
   1758         return false;
   1759     }
   1760 
   1761     //set alter handler This will start alert too
   1762     wifi_alert_handler alert_handler;
   1763     alert_handler.on_alert = &on_alert_data;
   1764     result = hal_fn.wifi_set_alert_handler(id, handle, alert_handler);
   1765     if (result != WIFI_SUCCESS) {
   1766         ALOGE(" Fail to set alert handler");
   1767         return false;
   1768     }
   1769 
   1770     return true;
   1771 }
   1772 
   1773 static jboolean android_net_wifi_reset_log_handler(JNIEnv *env, jclass cls, jint iface, jint id) {
   1774 
   1775     JNIHelper helper(env);
   1776     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1777 
   1778     //reset alter handler
   1779     ALOGD("android_net_wifi_reset_alert_handler = %p", handle);
   1780     int result = hal_fn.wifi_reset_alert_handler(id, handle);
   1781     if (result != WIFI_SUCCESS) {
   1782         ALOGE(" Fail to reset alert handler");
   1783         return false;
   1784     }
   1785 
   1786     //reset log handler
   1787     ALOGD("android_net_wifi_reset_log_handler = %p", handle);
   1788     result = hal_fn.wifi_reset_log_handler(id, handle);
   1789     if (result != WIFI_SUCCESS) {
   1790         ALOGE("Fail to reset logging handler");
   1791         return false;
   1792     }
   1793 
   1794     return true;
   1795 }
   1796 
   1797 // ----------------------------------------------------------------------------
   1798 // ePno framework
   1799 // ----------------------------------------------------------------------------
   1800 
   1801 
   1802 static void onPnoNetworkFound(wifi_request_id id,
   1803                                           unsigned num_results, wifi_scan_result *results) {
   1804 
   1805     JNIHelper helper(mVM);
   1806 
   1807     ALOGD("onPnoNetworkFound called, vm = %p, obj = %p, num_results %u", mVM, mCls, num_results);
   1808 
   1809     if (results == 0 || num_results == 0) {
   1810        ALOGE("onPnoNetworkFound: Error no results");
   1811        return;
   1812     }
   1813 
   1814     jbyte *bytes;
   1815     JNIObject<jobjectArray> scanResults(helper, NULL);
   1816     //jbyteArray elements;
   1817 
   1818     for (unsigned i=0; i<num_results; i++) {
   1819 
   1820         JNIObject<jobject> scanResult = createScanResult(helper, &results[i]);
   1821         if (i == 0) {
   1822             scanResults = helper.newObjectArray(
   1823                     num_results, "android/net/wifi/ScanResult", scanResult);
   1824             if (scanResults == 0) {
   1825                 ALOGD("cant allocate array");
   1826             } else {
   1827                 ALOGD("allocated array %u", helper.getArrayLength(scanResults));
   1828             }
   1829         } else {
   1830             helper.setObjectArrayElement(scanResults, i, scanResult);
   1831         }
   1832 
   1833         ALOGD("Scan result with ie length %d, i %u, <%s> rssi=%d %02x:%02x:%02x:%02x:%02x:%02x",
   1834                 results->ie_length, i, results[i].ssid, results[i].rssi, results[i].bssid[0],
   1835                 results[i].bssid[1],results[i].bssid[2], results[i].bssid[3], results[i].bssid[4],
   1836                 results[i].bssid[5]);
   1837 
   1838         /*elements = helper.newByteArray(results->ie_length);
   1839         if (elements == NULL) {
   1840             ALOGE("Error in allocating array");
   1841             return;
   1842         }*/
   1843 
   1844         //ALOGD("onPnoNetworkFound: Setting byte array");
   1845 
   1846         //bytes = (jbyte *)&(results->ie_data[0]);
   1847         //helper.setByteArrayRegion(elements, 0, results->ie_length, bytes);
   1848 
   1849         //ALOGD("onPnoNetworkFound: Returning result");
   1850     }
   1851 
   1852 
   1853     ALOGD("calling report");
   1854 
   1855     helper.reportEvent(mCls, "onPnoNetworkFound", "(I[Landroid/net/wifi/ScanResult;)V", id,
   1856                scanResults.get());
   1857         ALOGD("free ref");
   1858 }
   1859 
   1860 static jboolean android_net_wifi_setPnoListNative(
   1861         JNIEnv *env, jclass cls, jint iface, jint id, jobject list)  {
   1862 
   1863     JNIHelper helper(env);
   1864     wifi_epno_handler handler;
   1865     handler.on_network_found = &onPnoNetworkFound;
   1866 
   1867     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1868     ALOGD("configure ePno list request [%d] = %p", id, handle);
   1869 
   1870     if (list == NULL) {
   1871         // stop pno
   1872         int result = hal_fn.wifi_set_epno_list(id, handle, 0, NULL, handler);
   1873         ALOGE(" setPnoListNative: STOP result = %d", result);
   1874         return result >= 0;
   1875     }
   1876 
   1877     wifi_epno_network net_list[MAX_PNO_SSID];
   1878     memset(&net_list, 0, sizeof(net_list));
   1879 
   1880     size_t len = helper.getArrayLength((jobjectArray)list);
   1881     if (len > (size_t)MAX_PNO_SSID) {
   1882         return false;
   1883     }
   1884 
   1885     for (unsigned int i = 0; i < len; i++) {
   1886 
   1887         JNIObject<jobject> pno_net = helper.getObjectArrayElement((jobjectArray)list, i);
   1888         if (pno_net == NULL) {
   1889             ALOGD("setPnoListNative: could not get element %d", i);
   1890             continue;
   1891         }
   1892 
   1893         JNIObject<jstring> sssid = helper.getStringField(pno_net, "SSID");
   1894         if (sssid == NULL) {
   1895               ALOGE("Error setPnoListNative: getting ssid field");
   1896               return false;
   1897         }
   1898 
   1899         ScopedUtfChars chars(env, (jstring)sssid.get());
   1900         const char *ssid = chars.c_str();
   1901         if (ssid == NULL) {
   1902              ALOGE("Error setPnoListNative: getting ssid");
   1903              return false;
   1904         }
   1905         int ssid_len = strnlen((const char*)ssid, 33);
   1906         if (ssid_len > 32) {
   1907            ALOGE("Error setPnoListNative: long ssid %u", strnlen((const char*)ssid, 256));
   1908            return false;
   1909         }
   1910 
   1911         if (ssid_len > 1 && ssid[0] == '"' && ssid[ssid_len-1])
   1912         {
   1913             // strip leading and trailing '"'
   1914             ssid++;
   1915             ssid_len-=2;
   1916         }
   1917         if (ssid_len == 0) {
   1918             ALOGE("Error setPnoListNative: zero length ssid, skip it");
   1919             continue;
   1920         }
   1921         memcpy(net_list[i].ssid, ssid, ssid_len);
   1922 
   1923         int rssit = helper.getIntField(pno_net, "rssi_threshold");
   1924         net_list[i].rssi_threshold = (byte)rssit;
   1925         int a = helper.getIntField(pno_net, "auth");
   1926         net_list[i].auth_bit_field = a;
   1927         int f = helper.getIntField(pno_net, "flags");
   1928         net_list[i].flags = f;
   1929         ALOGE(" setPnoListNative: idx %u rssi %d/%d auth %x/%x flags %x/%x [%s]", i,
   1930                 (signed)net_list[i].rssi_threshold, net_list[i].rssi_threshold,
   1931                 net_list[i].auth_bit_field, a, net_list[i].flags, f, net_list[i].ssid);
   1932     }
   1933 
   1934     int result = hal_fn.wifi_set_epno_list(id, handle, len, net_list, handler);
   1935     ALOGE(" setPnoListNative: result %d", result);
   1936 
   1937     return result >= 0;
   1938 }
   1939 
   1940 static jboolean android_net_wifi_setLazyRoam(
   1941         JNIEnv *env, jclass cls, jint iface, jint id, jboolean enabled, jobject roam_param)  {
   1942 
   1943     JNIHelper helper(env);
   1944     wifi_error status = WIFI_SUCCESS;
   1945     wifi_roam_params params;
   1946     memset(&params, 0, sizeof(params));
   1947 
   1948     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1949     ALOGD("configure lazy roam request [%d] = %p", id, handle);
   1950 
   1951     if (roam_param != NULL) {
   1952         params.A_band_boost_threshold  = helper.getIntField(roam_param, "A_band_boost_threshold");
   1953         params.A_band_penalty_threshold  = helper.getIntField(roam_param, "A_band_penalty_threshold");
   1954         params.A_band_boost_factor = helper.getIntField(roam_param, "A_band_boost_factor");
   1955         params.A_band_penalty_factor  = helper.getIntField(roam_param, "A_band_penalty_factor");
   1956         params.A_band_max_boost  = helper.getIntField(roam_param, "A_band_max_boost");
   1957         params.lazy_roam_hysteresis = helper.getIntField(roam_param, "lazy_roam_hysteresis");
   1958         params.alert_roam_rssi_trigger = helper.getIntField(roam_param, "alert_roam_rssi_trigger");
   1959         status = hal_fn.wifi_set_gscan_roam_params(id, handle, &params);
   1960     }
   1961     ALOGE("android_net_wifi_setLazyRoam configured params status=%d\n", status);
   1962 
   1963     if (status >= 0) {
   1964         int doEnable = enabled ? 1 : 0;
   1965         status = hal_fn.wifi_enable_lazy_roam(id, handle, doEnable);
   1966         ALOGE("android_net_wifi_setLazyRoam enabled roam status=%d\n", status);
   1967     }
   1968     return status >= 0;
   1969 }
   1970 
   1971 static jboolean android_net_wifi_setBssidBlacklist(
   1972         JNIEnv *env, jclass cls, jint iface, jint id, jobject list)  {
   1973 
   1974     JNIHelper helper(env);
   1975     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   1976     ALOGD("configure BSSID black list request [%d] = %p", id, handle);
   1977 
   1978     wifi_bssid_params params;
   1979     memset(&params, 0, sizeof(params));
   1980 
   1981     if (list != NULL) {
   1982         size_t len = helper.getArrayLength((jobjectArray)list);
   1983         if (len > (size_t)MAX_BLACKLIST_BSSID) {
   1984             return false;
   1985         }
   1986         for (unsigned int i = 0; i < len; i++) {
   1987 
   1988             JNIObject<jobject> jbssid = helper.getObjectArrayElement(list, i);
   1989             if (jbssid == NULL) {
   1990                 ALOGD("configure BSSID blacklist: could not get element %d", i);
   1991                 continue;
   1992             }
   1993 
   1994             ScopedUtfChars chars(env, (jstring)jbssid.get());
   1995             const char *bssid = chars.c_str();
   1996             if (bssid == NULL) {
   1997                 ALOGE("Error getting bssid");
   1998                 return false;
   1999             }
   2000 
   2001             mac_addr addr;
   2002             parseMacAddress(bssid, addr);
   2003             memcpy(params.bssids[i], addr, sizeof(mac_addr));
   2004 
   2005             char bssidOut[32];
   2006             sprintf(bssidOut, "%0x:%0x:%0x:%0x:%0x:%0x", addr[0], addr[1],
   2007                 addr[2], addr[3], addr[4], addr[5]);
   2008 
   2009             ALOGD("BSSID blacklist: added bssid %s", bssidOut);
   2010 
   2011             params.num_bssid++;
   2012         }
   2013     }
   2014 
   2015     ALOGD("Added %d bssids", params.num_bssid);
   2016     return hal_fn.wifi_set_bssid_blacklist(id, handle, params) == WIFI_SUCCESS;
   2017 }
   2018 
   2019 static jboolean android_net_wifi_setSsidWhitelist(
   2020         JNIEnv *env, jclass cls, jint iface, jint id, jobject list)  {
   2021 
   2022     JNIHelper helper(env);
   2023     wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
   2024     ALOGD("configure SSID white list request [%d] = %p", id, handle);
   2025     wifi_ssid *ssids = NULL;
   2026     int num_ssids = 0;
   2027     if (list != NULL) {
   2028         size_t len = helper.getArrayLength((jobjectArray)list);
   2029         if (len > 0) {
   2030             ssids = (wifi_ssid *)malloc(len * sizeof (wifi_ssid));
   2031             if (!ssids) return false;
   2032             memset(ssids, 0, len * sizeof (wifi_ssid));
   2033             for (unsigned int i = 0; i < len; i++) {
   2034 
   2035                 JNIObject<jobject> jssid = helper.getObjectArrayElement(list, i);
   2036                 if (jssid == NULL) {
   2037                     ALOGD("configure SSID whitelist: could not get element %d", i);
   2038                     free(ssids);
   2039                    return false;
   2040                 }
   2041 
   2042                 ScopedUtfChars chars(env, (jstring)jssid.get());
   2043                 const char *utf = chars.c_str();
   2044                 if (utf == NULL) {
   2045                     ALOGE("Error getting sssid");
   2046                     free(ssids);
   2047                     return false;
   2048                 }
   2049 
   2050                 int slen = strnlen(utf, 33);
   2051                 if (slen <= 0 || slen > 32) {
   2052                     ALOGE("Error wrong ssid length %d", slen);
   2053                     free(ssids);
   2054                     return false;
   2055                 }
   2056 
   2057                 memcpy(ssids[i].ssid, utf, slen);
   2058                 num_ssids++;
   2059                 ALOGD("SSID white list: added ssid %s", utf);
   2060             }
   2061         }
   2062     }
   2063 
   2064     ALOGD("android_net_wifi_setSsidWhitelist Added %d sssids", num_ssids);
   2065     return hal_fn.wifi_set_ssid_white_list(id, handle, num_ssids, ssids) == WIFI_SUCCESS;
   2066 }
   2067 
   2068 // ----------------------------------------------------------------------------
   2069 
   2070 /*
   2071  * JNI registration.
   2072  */
   2073 static JNINativeMethod gWifiMethods[] = {
   2074     /* name, signature, funcPtr */
   2075 
   2076     { "loadDriver", "()Z",  (void *)android_net_wifi_loadDriver },
   2077     { "isDriverLoaded", "()Z",  (void *)android_net_wifi_isDriverLoaded },
   2078     { "unloadDriver", "()Z",  (void *)android_net_wifi_unloadDriver },
   2079     { "startSupplicant", "(Z)Z",  (void *)android_net_wifi_startSupplicant },
   2080     { "killSupplicant", "(Z)Z",  (void *)android_net_wifi_killSupplicant },
   2081     { "connectToSupplicantNative", "()Z", (void *)android_net_wifi_connectToSupplicant },
   2082     { "closeSupplicantConnectionNative", "()V",
   2083             (void *)android_net_wifi_closeSupplicantConnection },
   2084     { "waitForEventNative", "()Ljava/lang/String;", (void*)android_net_wifi_waitForEvent },
   2085     { "doBooleanCommandNative", "(Ljava/lang/String;)Z", (void*)android_net_wifi_doBooleanCommand },
   2086     { "doIntCommandNative", "(Ljava/lang/String;)I", (void*)android_net_wifi_doIntCommand },
   2087     { "doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;",
   2088             (void*) android_net_wifi_doStringCommand },
   2089     { "startHalNative", "()Z", (void*) android_net_wifi_startHal },
   2090     { "stopHalNative", "()V", (void*) android_net_wifi_stopHal },
   2091     { "waitForHalEventNative", "()V", (void*) android_net_wifi_waitForHalEvents },
   2092     { "getInterfacesNative", "()I", (void*) android_net_wifi_getInterfaces},
   2093     { "getInterfaceNameNative", "(I)Ljava/lang/String;", (void*) android_net_wifi_getInterfaceName},
   2094     { "getScanCapabilitiesNative", "(ILcom/android/server/wifi/WifiNative$ScanCapabilities;)Z",
   2095             (void *) android_net_wifi_getScanCapabilities},
   2096     { "startScanNative", "(IILcom/android/server/wifi/WifiNative$ScanSettings;)Z",
   2097             (void*) android_net_wifi_startScan},
   2098     { "stopScanNative", "(II)Z", (void*) android_net_wifi_stopScan},
   2099     { "getScanResultsNative", "(IZ)[Landroid/net/wifi/WifiScanner$ScanData;",
   2100             (void *) android_net_wifi_getScanResults},
   2101     { "setHotlistNative", "(IILandroid/net/wifi/WifiScanner$HotlistSettings;)Z",
   2102             (void*) android_net_wifi_setHotlist},
   2103     { "resetHotlistNative", "(II)Z", (void*) android_net_wifi_resetHotlist},
   2104     { "trackSignificantWifiChangeNative", "(IILandroid/net/wifi/WifiScanner$WifiChangeSettings;)Z",
   2105             (void*) android_net_wifi_trackSignificantWifiChange},
   2106     { "untrackSignificantWifiChangeNative", "(II)Z",
   2107             (void*) android_net_wifi_untrackSignificantWifiChange},
   2108     { "getWifiLinkLayerStatsNative", "(I)Landroid/net/wifi/WifiLinkLayerStats;",
   2109             (void*) android_net_wifi_getLinkLayerStats},
   2110     { "setWifiLinkLayerStatsNative", "(II)V",
   2111             (void*) android_net_wifi_setLinkLayerStats},
   2112     { "getSupportedFeatureSetNative", "(I)I",
   2113             (void*) android_net_wifi_getSupportedFeatures},
   2114     { "requestRangeNative", "(II[Landroid/net/wifi/RttManager$RttParams;)Z",
   2115             (void*) android_net_wifi_requestRange},
   2116     { "cancelRangeRequestNative", "(II[Landroid/net/wifi/RttManager$RttParams;)Z",
   2117             (void*) android_net_wifi_cancelRange},
   2118     { "setScanningMacOuiNative", "(I[B)Z",  (void*) android_net_wifi_setScanningMacOui},
   2119     { "getChannelsForBandNative", "(II)[I", (void*) android_net_wifi_getValidChannels},
   2120     { "setDfsFlagNative",         "(IZ)Z",  (void*) android_net_wifi_setDfsFlag},
   2121     { "toggleInterfaceNative",    "(I)Z",  (void*) android_net_wifi_toggle_interface},
   2122     { "getRttCapabilitiesNative", "(I)Landroid/net/wifi/RttManager$RttCapabilities;",
   2123             (void*) android_net_wifi_get_rtt_capabilities},
   2124     {"setCountryCodeHalNative", "(ILjava/lang/String;)Z",
   2125             (void*) android_net_wifi_set_Country_Code_Hal},
   2126     { "setPnoListNative", "(II[Lcom/android/server/wifi/WifiNative$WifiPnoNetwork;)Z",
   2127             (void*) android_net_wifi_setPnoListNative},
   2128     {"enableDisableTdlsNative", "(IZLjava/lang/String;)Z",
   2129             (void*) android_net_wifi_enable_disable_tdls},
   2130     {"getTdlsStatusNative", "(ILjava/lang/String;)Lcom/android/server/wifi/WifiNative$TdlsStatus;",
   2131             (void*) android_net_wifi_get_tdls_status},
   2132     {"getTdlsCapabilitiesNative", "(I)Lcom/android/server/wifi/WifiNative$TdlsCapabilities;",
   2133             (void*) android_net_wifi_get_tdls_capabilities},
   2134     {"getSupportedLoggerFeatureSetNative","(I)I",
   2135             (void*) android_net_wifi_get_supported_logger_feature},
   2136     {"getDriverVersionNative", "(I)Ljava/lang/String;",
   2137             (void*) android_net_wifi_get_driver_version},
   2138     {"getFirmwareVersionNative", "(I)Ljava/lang/String;",
   2139             (void*) android_net_wifi_get_firmware_version},
   2140     {"getRingBufferStatusNative", "(I)[Lcom/android/server/wifi/WifiNative$RingBufferStatus;",
   2141             (void*) android_net_wifi_get_ring_buffer_status},
   2142     {"startLoggingRingBufferNative", "(IIIIILjava/lang/String;)Z",
   2143             (void*) android_net_wifi_start_logging_ring_buffer},
   2144     {"getRingBufferDataNative", "(ILjava/lang/String;)Z",
   2145             (void*) android_net_wifi_get_ring_buffer_data},
   2146     {"getFwMemoryDumpNative","(I)Z", (void*) android_net_wifi_get_fw_memory_dump},
   2147     { "setLazyRoamNative", "(IIZLcom/android/server/wifi/WifiNative$WifiLazyRoamParams;)Z",
   2148             (void*) android_net_wifi_setLazyRoam},
   2149     { "setBssidBlacklistNative", "(II[Ljava/lang/String;)Z",
   2150             (void*)android_net_wifi_setBssidBlacklist},
   2151     { "setSsidWhitelistNative", "(II[Ljava/lang/String;)Z",
   2152             (void*)android_net_wifi_setSsidWhitelist},
   2153     {"setLoggingEventHandlerNative", "(II)Z", (void *) android_net_wifi_set_log_handler},
   2154     {"resetLogHandlerNative", "(II)Z", (void *) android_net_wifi_reset_log_handler},
   2155     {"isGetChannelsForBandSupportedNative", "()Z",
   2156             (void*)android_net_wifi_is_get_channels_for_band_supported}
   2157 };
   2158 
   2159 int register_android_net_wifi_WifiNative(JNIEnv* env) {
   2160     return AndroidRuntime::registerNativeMethods(env,
   2161             "com/android/server/wifi/WifiNative", gWifiMethods, NELEM(gWifiMethods));
   2162 }
   2163 
   2164 
   2165 /* User to register native functions */
   2166 extern "C"
   2167 jint Java_com_android_server_wifi_WifiNative_registerNatives(JNIEnv* env, jclass clazz) {
   2168     return AndroidRuntime::registerNativeMethods(env,
   2169             "com/android/server/wifi/WifiNative", gWifiMethods, NELEM(gWifiMethods));
   2170 }
   2171 
   2172 }; // namespace android
   2173