com_android_server_wifi_WifiNative.cpp revision 5ee18dc63952ff80f4ea21296a0df4f7b27eafe6
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 <ScopedUtfChars.h> 21#include <utils/misc.h> 22#include <android_runtime/AndroidRuntime.h> 23#include <utils/Log.h> 24#include <utils/String16.h> 25#include <ctype.h> 26#include <sys/socket.h> 27#include <linux/if.h> 28 29#include "wifi.h" 30#include "wifi_hal.h" 31#include "jni_helper.h" 32#include "rtt.h" 33#include "wifi_hal_stub.h" 34#define REPLY_BUF_SIZE 4096 // wpa_supplicant's maximum size. 35#define EVENT_BUF_SIZE 2048 36 37namespace android { 38 39static jint DBG = false; 40 41//Please put all HAL function call here and call from the function table instead of directly call 42static wifi_hal_fn hal_fn; 43int init_wifi_hal_func_table(wifi_hal_fn *hal_fn) { 44 if (hal_fn == NULL) { 45 return -1; 46 } 47 hal_fn->wifi_initialize = wifi_initialize_stub; 48 hal_fn->wifi_cleanup = wifi_cleanup_stub; 49 hal_fn->wifi_event_loop = wifi_event_loop_stub; 50 hal_fn->wifi_get_error_info = wifi_get_error_info_stub; 51 hal_fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set_stub; 52 hal_fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix_stub; 53 hal_fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui_stub; 54 hal_fn->wifi_get_supported_channels = wifi_get_supported_channels_stub; 55 hal_fn->wifi_is_epr_supported = wifi_is_epr_supported_stub; 56 hal_fn->wifi_get_ifaces = wifi_get_ifaces_stub; 57 hal_fn->wifi_get_iface_name = wifi_get_iface_name_stub; 58 hal_fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler_stub; 59 hal_fn->wifi_start_gscan = wifi_start_gscan_stub; 60 hal_fn->wifi_stop_gscan = wifi_stop_gscan_stub; 61 hal_fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results_stub; 62 hal_fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist_stub; 63 hal_fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist_stub; 64 hal_fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler_stub; 65 hal_fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler_stub; 66 hal_fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities_stub; 67 hal_fn->wifi_set_link_stats = wifi_set_link_stats_stub; 68 hal_fn->wifi_get_link_stats = wifi_get_link_stats_stub; 69 hal_fn->wifi_clear_link_stats = wifi_clear_link_stats_stub; 70 hal_fn->wifi_get_valid_channels = wifi_get_valid_channels_stub; 71 hal_fn->wifi_rtt_range_request = wifi_rtt_range_request_stub; 72 hal_fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel_stub; 73 hal_fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities_stub; 74 hal_fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag_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 return 0; 79} 80 81static bool doCommand(JNIEnv* env, jstring javaCommand, 82 char* reply, size_t reply_len) { 83 ScopedUtfChars command(env, javaCommand); 84 if (command.c_str() == NULL) { 85 return false; // ScopedUtfChars already threw on error. 86 } 87 88 if (DBG) { 89 ALOGD("doCommand: %s", command.c_str()); 90 } 91 92 --reply_len; // Ensure we have room to add NUL termination. 93 if (::wifi_command(command.c_str(), reply, &reply_len) != 0) { 94 return false; 95 } 96 97 // Strip off trailing newline. 98 if (reply_len > 0 && reply[reply_len-1] == '\n') { 99 reply[reply_len-1] = '\0'; 100 } else { 101 reply[reply_len] = '\0'; 102 } 103 return true; 104} 105 106static jint doIntCommand(JNIEnv* env, jstring javaCommand) { 107 char reply[REPLY_BUF_SIZE]; 108 if (!doCommand(env, javaCommand, reply, sizeof(reply))) { 109 return -1; 110 } 111 return static_cast<jint>(atoi(reply)); 112} 113 114static jboolean doBooleanCommand(JNIEnv* env, jstring javaCommand) { 115 char reply[REPLY_BUF_SIZE]; 116 if (!doCommand(env, javaCommand, reply, sizeof(reply))) { 117 return JNI_FALSE; 118 } 119 return (strcmp(reply, "OK") == 0); 120} 121 122// Send a command to the supplicant, and return the reply as a String. 123static jstring doStringCommand(JNIEnv* env, jstring javaCommand) { 124 char reply[REPLY_BUF_SIZE]; 125 if (!doCommand(env, javaCommand, reply, sizeof(reply))) { 126 return NULL; 127 } 128 return env->NewStringUTF(reply); 129} 130 131static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject) 132{ 133 return (::is_wifi_driver_loaded() == 1); 134} 135 136static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject) 137{ 138 return (::wifi_load_driver() == 0); 139} 140 141static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject) 142{ 143 return (::wifi_unload_driver() == 0); 144} 145 146static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject, jboolean p2pSupported) 147{ 148 return (::wifi_start_supplicant(p2pSupported) == 0); 149} 150 151static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject, jboolean p2pSupported) 152{ 153 return (::wifi_stop_supplicant(p2pSupported) == 0); 154} 155 156static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject) 157{ 158 return (::wifi_connect_to_supplicant() == 0); 159} 160 161static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject) 162{ 163 ::wifi_close_supplicant_connection(); 164} 165 166static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject) 167{ 168 char buf[EVENT_BUF_SIZE]; 169 int nread = ::wifi_wait_for_event(buf, sizeof buf); 170 if (nread > 0) { 171 return env->NewStringUTF(buf); 172 } else { 173 return NULL; 174 } 175} 176 177static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring javaCommand) { 178 return doBooleanCommand(env, javaCommand); 179} 180 181static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring javaCommand) { 182 return doIntCommand(env, javaCommand); 183} 184 185static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring javaCommand) { 186 return doStringCommand(env,javaCommand); 187} 188 189/* wifi_hal <==> WifiNative bridge */ 190 191static jclass mCls; /* saved WifiNative object */ 192static JavaVM *mVM; /* saved JVM pointer */ 193 194static const char *WifiHandleVarName = "sWifiHalHandle"; 195static const char *WifiIfaceHandleVarName = "sWifiIfaceHandles"; 196static jmethodID OnScanResultsMethodID; 197 198static JNIEnv *getEnv() { 199 JNIEnv *env = NULL; 200 mVM->AttachCurrentThread(&env, NULL); 201 return env; 202} 203 204static wifi_handle getWifiHandle(JNIEnv *env, jclass cls) { 205 return (wifi_handle) getStaticLongField(env, cls, WifiHandleVarName); 206} 207 208static wifi_interface_handle getIfaceHandle(JNIEnv *env, jclass cls, jint index) { 209 return (wifi_interface_handle) getStaticLongArrayField(env, cls, WifiIfaceHandleVarName, index); 210} 211 212static jobject createScanResult(JNIEnv *env, wifi_scan_result *result) { 213 214 // ALOGD("creating scan result"); 215 216 jobject scanResult = createObject(env, "android/net/wifi/ScanResult"); 217 if (scanResult == NULL) { 218 ALOGE("Error in creating scan result"); 219 return NULL; 220 } 221 222 // ALOGD("setting SSID to %s", result.ssid); 223 setStringField(env, scanResult, "SSID", result->ssid); 224 225 char bssid[32]; 226 sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result->bssid[0], result->bssid[1], 227 result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]); 228 229 setStringField(env, scanResult, "BSSID", bssid); 230 231 setIntField(env, scanResult, "level", result->rssi); 232 setIntField(env, scanResult, "frequency", result->channel); 233 setLongField(env, scanResult, "timestamp", result->ts); 234 235 return scanResult; 236} 237 238int set_iface_flags(const char *ifname, int dev_up) { 239 struct ifreq ifr; 240 int ret; 241 int sock = socket(PF_INET, SOCK_DGRAM, 0); 242 if (sock < 0) { 243 ALOGD("Bad socket: %d\n", sock); 244 return -errno; 245 } 246 247 ALOGD("setting interface %s flags (%s)\n", ifname, dev_up ? "UP" : "DOWN"); 248 249 memset(&ifr, 0, sizeof(ifr)); 250 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); 251 252 ALOGD("reading old value\n"); 253 254 if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) { 255 ret = errno ? -errno : -999; 256 ALOGD("Could not read interface %s flags: %d\n", ifname, errno); 257 close(sock); 258 return ret; 259 } else { 260 ALOGD("writing new value\n"); 261 } 262 263 if (dev_up) { 264 if (ifr.ifr_flags & IFF_UP) { 265 ALOGD("interface %s is already up\n", ifname); 266 close(sock); 267 return 0; 268 } 269 ifr.ifr_flags |= IFF_UP; 270 } else { 271 if (!(ifr.ifr_flags & IFF_UP)) { 272 ALOGD("interface %s is already down\n", ifname); 273 close(sock); 274 return 0; 275 } 276 ifr.ifr_flags &= ~IFF_UP; 277 } 278 279 if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) { 280 ALOGD("Could not set interface %s flags \n", ifname); 281 close(sock); 282 return ret; 283 } else { 284 ALOGD("set interface %s flags (%s)\n", ifname, dev_up ? "UP" : "DOWN"); 285 } 286 close(sock); 287 return 0; 288} 289 290static jboolean android_net_wifi_toggle_interface(JNIEnv* env, jclass cls, int toggle) { 291 return(set_iface_flags("wlan0", toggle) == 0); 292} 293 294static jboolean android_net_wifi_startHal(JNIEnv* env, jclass cls) { 295 wifi_handle halHandle = getWifiHandle(env, cls); 296 if (halHandle == NULL) { 297 298 if(init_wifi_hal_func_table(&hal_fn) != 0 ) { 299 ALOGD("Can not initialize the basic function pointer table"); 300 return false; 301 } 302 303 wifi_error res = init_wifi_vendor_hal_func_table(&hal_fn); 304 if (res != WIFI_SUCCESS) { 305 ALOGD("Can not initialize the vendor function pointer table"); 306 return false; 307 } 308 309 int ret = set_iface_flags("wlan0", 1); 310 if(ret != 0) { 311 return false; 312 } 313 314 res = hal_fn.wifi_initialize(&halHandle); 315 if (res == WIFI_SUCCESS) { 316 setStaticLongField(env, cls, WifiHandleVarName, (jlong)halHandle); 317 ALOGD("Did set static halHandle = %p", halHandle); 318 } 319 env->GetJavaVM(&mVM); 320 mCls = (jclass) env->NewGlobalRef(cls); 321 ALOGD("halHandle = %p, mVM = %p, mCls = %p", halHandle, mVM, mCls); 322 return res == WIFI_SUCCESS; 323 } else { 324 return (set_iface_flags("wlan0", 1) == 0); 325 } 326} 327 328void android_net_wifi_hal_cleaned_up_handler(wifi_handle handle) { 329 ALOGD("In wifi cleaned up handler"); 330 331 JNIEnv * env = getEnv(); 332 setStaticLongField(env, mCls, WifiHandleVarName, 0); 333 env->DeleteGlobalRef(mCls); 334 mCls = NULL; 335 mVM = NULL; 336} 337 338static void android_net_wifi_stopHal(JNIEnv* env, jclass cls) { 339 ALOGD("In wifi stop Hal"); 340 341 wifi_handle halHandle = getWifiHandle(env, cls); 342 hal_fn.wifi_cleanup(halHandle, android_net_wifi_hal_cleaned_up_handler); 343 set_iface_flags("wlan0", 0); 344} 345 346static void android_net_wifi_waitForHalEvents(JNIEnv* env, jclass cls) { 347 348 ALOGD("waitForHalEvents called, vm = %p, obj = %p, env = %p", mVM, mCls, env); 349 350 wifi_handle halHandle = getWifiHandle(env, cls); 351 hal_fn.wifi_event_loop(halHandle); 352} 353 354static int android_net_wifi_getInterfaces(JNIEnv *env, jclass cls) { 355 int n = 0; 356 wifi_handle halHandle = getWifiHandle(env, cls); 357 wifi_interface_handle *ifaceHandles = NULL; 358 int result = hal_fn.wifi_get_ifaces(halHandle, &n, &ifaceHandles); 359 if (result < 0) { 360 return result; 361 } 362 363 if (n < 0) { 364 THROW(env, "android_net_wifi_getInterfaces no interfaces"); 365 return 0; 366 } 367 368 if (ifaceHandles == NULL) { 369 THROW(env, "android_net_wifi_getInterfaces null interface array"); 370 return 0; 371 } 372 373 if (n > 8) { 374 THROW(env, "Too many interfaces"); 375 return 0; 376 } 377 378 jlongArray array = (env)->NewLongArray(n); 379 if (array == NULL) { 380 THROW(env, "Error in accessing array"); 381 return 0; 382 } 383 384 jlong elems[8]; 385 for (int i = 0; i < n; i++) { 386 elems[i] = reinterpret_cast<jlong>(ifaceHandles[i]); 387 } 388 env->SetLongArrayRegion(array, 0, n, elems); 389 setStaticLongArrayField(env, cls, WifiIfaceHandleVarName, array); 390 391 return (result < 0) ? result : n; 392} 393 394static jstring android_net_wifi_getInterfaceName(JNIEnv *env, jclass cls, jint i) { 395 char buf[EVENT_BUF_SIZE]; 396 397 jlong value = getStaticLongArrayField(env, cls, WifiIfaceHandleVarName, i); 398 wifi_interface_handle handle = (wifi_interface_handle) value; 399 int result = hal_fn.wifi_get_iface_name(handle, buf, sizeof(buf)); 400 if (result < 0) { 401 return NULL; 402 } else { 403 return env->NewStringUTF(buf); 404 } 405} 406 407 408static void onScanResultsAvailable(wifi_request_id id, unsigned num_results) { 409 410 JNIEnv *env = NULL; 411 mVM->AttachCurrentThread(&env, NULL); 412 413 ALOGD("onScanResultsAvailable called, vm = %p, obj = %p, env = %p", mVM, mCls, env); 414 415 reportEvent(env, mCls, "onScanResultsAvailable", "(I)V", id); 416} 417 418static void onScanEvent(wifi_scan_event event, unsigned status) { 419 JNIEnv *env = NULL; 420 mVM->AttachCurrentThread(&env, NULL); 421 422 ALOGD("onScanStatus called, vm = %p, obj = %p, env = %p", mVM, mCls, env); 423 424 reportEvent(env, mCls, "onScanStatus", "(I)V", event); 425} 426 427static void onFullScanResult(wifi_request_id id, wifi_scan_result *result) { 428 429 JNIEnv *env = NULL; 430 mVM->AttachCurrentThread(&env, NULL); 431 432 ALOGD("onFullScanResult called, vm = %p, obj = %p, env = %p", mVM, mCls, env); 433 434 jobject scanResult = createScanResult(env, result); 435 436 ALOGD("Creating a byte array of length %d", result->ie_length); 437 438 jbyteArray elements = env->NewByteArray(result->ie_length); 439 if (elements == NULL) { 440 ALOGE("Error in allocating array"); 441 return; 442 } 443 444 ALOGE("Setting byte array"); 445 446 jbyte *bytes = (jbyte *)&(result->ie_data[0]); 447 env->SetByteArrayRegion(elements, 0, result->ie_length, bytes); 448 449 ALOGE("Returning result"); 450 451 reportEvent(env, mCls, "onFullScanResult", "(ILandroid/net/wifi/ScanResult;[B)V", id, 452 scanResult, elements); 453 454 env->DeleteLocalRef(scanResult); 455 env->DeleteLocalRef(elements); 456} 457 458static jboolean android_net_wifi_startScan( 459 JNIEnv *env, jclass cls, jint iface, jint id, jobject settings) { 460 461 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 462 ALOGD("starting scan on interface[%d] = %p", iface, handle); 463 464 wifi_scan_cmd_params params; 465 memset(¶ms, 0, sizeof(params)); 466 467 params.base_period = getIntField(env, settings, "base_period_ms"); 468 params.max_ap_per_scan = getIntField(env, settings, "max_ap_per_scan"); 469 params.report_threshold_percent = getIntField(env, settings, "report_threshold_percent"); 470 params.report_threshold_num_scans = getIntField(env, settings, "report_threshold_num_scans"); 471 472 ALOGD("Initialized common fields %d, %d, %d, %d", params.base_period, params.max_ap_per_scan, 473 params.report_threshold_percent, params.report_threshold_num_scans); 474 475 const char *bucket_array_type = "[Lcom/android/server/wifi/WifiNative$BucketSettings;"; 476 const char *channel_array_type = "[Lcom/android/server/wifi/WifiNative$ChannelSettings;"; 477 478 jobjectArray buckets = (jobjectArray)getObjectField(env, settings, "buckets", bucket_array_type); 479 params.num_buckets = getIntField(env, settings, "num_buckets"); 480 481 ALOGD("Initialized num_buckets to %d", params.num_buckets); 482 483 for (int i = 0; i < params.num_buckets; i++) { 484 jobject bucket = getObjectArrayField(env, settings, "buckets", bucket_array_type, i); 485 486 params.buckets[i].bucket = getIntField(env, bucket, "bucket"); 487 params.buckets[i].band = (wifi_band) getIntField(env, bucket, "band"); 488 params.buckets[i].period = getIntField(env, bucket, "period_ms"); 489 490 ALOGD("Initialized common bucket fields %d:%d:%d", params.buckets[i].bucket, 491 params.buckets[i].band, params.buckets[i].period); 492 493 int report_events = getIntField(env, bucket, "report_events"); 494 params.buckets[i].report_events = report_events; 495 496 ALOGD("Initialized report events to %d", params.buckets[i].report_events); 497 498 jobjectArray channels = (jobjectArray)getObjectField( 499 env, bucket, "channels", channel_array_type); 500 501 params.buckets[i].num_channels = getIntField(env, bucket, "num_channels"); 502 ALOGD("Initialized num_channels to %d", params.buckets[i].num_channels); 503 504 for (int j = 0; j < params.buckets[i].num_channels; j++) { 505 jobject channel = getObjectArrayField(env, bucket, "channels", channel_array_type, j); 506 507 params.buckets[i].channels[j].channel = getIntField(env, channel, "frequency"); 508 params.buckets[i].channels[j].dwellTimeMs = getIntField(env, channel, "dwell_time_ms"); 509 510 bool passive = getBoolField(env, channel, "passive"); 511 params.buckets[i].channels[j].passive = (passive ? 1 : 0); 512 513 ALOGD("Initialized channel %d", params.buckets[i].channels[j].channel); 514 } 515 } 516 517 ALOGD("Initialized all fields"); 518 519 wifi_scan_result_handler handler; 520 memset(&handler, 0, sizeof(handler)); 521 handler.on_scan_results_available = &onScanResultsAvailable; 522 handler.on_full_scan_result = &onFullScanResult; 523 handler.on_scan_event = &onScanEvent; 524 525 return hal_fn.wifi_start_gscan(id, handle, params, handler) == WIFI_SUCCESS; 526} 527 528static jboolean android_net_wifi_stopScan(JNIEnv *env, jclass cls, jint iface, jint id) { 529 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 530 ALOGD("stopping scan on interface[%d] = %p", iface, handle); 531 532 return hal_fn.wifi_stop_gscan(id, handle) == WIFI_SUCCESS; 533} 534 535static int compare_scan_result_timestamp(const void *v1, const void *v2) { 536 const wifi_scan_result *result1 = static_cast<const wifi_scan_result *>(v1); 537 const wifi_scan_result *result2 = static_cast<const wifi_scan_result *>(v2); 538 return result1->ts - result2->ts; 539} 540 541static jobject android_net_wifi_getScanResults( 542 JNIEnv *env, jclass cls, jint iface, jboolean flush) { 543 544 wifi_cached_scan_results scan_data[64]; 545 int num_scan_data = 64; 546 547 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 548 ALOGD("getting scan results on interface[%d] = %p", iface, handle); 549 550 byte b = flush ? 0 : 0xFF; 551 int result = hal_fn.wifi_get_cached_gscan_results(handle, b, num_scan_data, scan_data, &num_scan_data); 552 if (result == WIFI_SUCCESS) { 553 jobjectArray scanData = createObjectArray(env, 554 "android/net/wifi/WifiScanner$ScanData", num_scan_data); 555 if (scanData == NULL) { 556 ALOGE("Error in allocating array of scanData"); 557 return NULL; 558 } 559 560 for (int i = 0; i < num_scan_data; i++) { 561 562 jobject data = createObject(env, "android/net/wifi/WifiScanner$ScanData"); 563 if (data == NULL) { 564 ALOGE("Error in allocating scanData"); 565 return NULL; 566 } 567 568 setIntField(env, data, "mId", scan_data[i].scan_id); 569 setIntField(env, data, "mFlags", scan_data[i].flags); 570 571 /* sort all scan results by timestamp */ 572 qsort(scan_data[i].results, scan_data[i].num_results, 573 sizeof(wifi_scan_result), compare_scan_result_timestamp); 574 575 jobjectArray scanResults = createObjectArray(env, 576 "android/net/wifi/ScanResult", scan_data[i].num_results); 577 if (scanResults == NULL) { 578 ALOGE("Error in allocating scanResult array"); 579 return NULL; 580 } 581 582 wifi_scan_result *results = scan_data[i].results; 583 for (int j = 0; j < scan_data[i].num_results; j++) { 584 585 jobject scanResult = createObject(env, "android/net/wifi/ScanResult"); 586 if (scanResult == NULL) { 587 ALOGE("Error in creating scan result"); 588 return NULL; 589 } 590 591 setStringField(env, scanResult, "SSID", results[j].ssid); 592 593 char bssid[32]; 594 sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", results[j].bssid[0], 595 results[j].bssid[1], results[j].bssid[2], results[j].bssid[3], 596 results[j].bssid[4], results[j].bssid[5]); 597 598 setStringField(env, scanResult, "BSSID", bssid); 599 600 setIntField(env, scanResult, "level", results[j].rssi); 601 setIntField(env, scanResult, "frequency", results[j].channel); 602 setLongField(env, scanResult, "timestamp", results[j].ts); 603 604 env->SetObjectArrayElement(scanResults, j, scanResult); 605 env->DeleteLocalRef(scanResult); 606 } 607 608 setObjectField(env, data, "mResults", "[Landroid/net/wifi/ScanResult;", scanResults); 609 env->SetObjectArrayElement(scanData, i, data); 610 } 611 612 return scanData; 613 } else { 614 return NULL; 615 } 616} 617 618 619static jboolean android_net_wifi_getScanCapabilities( 620 JNIEnv *env, jclass cls, jint iface, jobject capabilities) { 621 622 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 623 ALOGD("getting scan capabilities on interface[%d] = %p", iface, handle); 624 625 wifi_gscan_capabilities c; 626 memset(&c, 0, sizeof(c)); 627 int result = hal_fn.wifi_get_gscan_capabilities(handle, &c); 628 if (result != WIFI_SUCCESS) { 629 ALOGD("failed to get capabilities : %d", result); 630 return JNI_FALSE; 631 } 632 633 setIntField(env, capabilities, "max_scan_cache_size", c.max_scan_cache_size); 634 setIntField(env, capabilities, "max_scan_buckets", c.max_scan_buckets); 635 setIntField(env, capabilities, "max_ap_cache_per_scan", c.max_ap_cache_per_scan); 636 setIntField(env, capabilities, "max_rssi_sample_size", c.max_rssi_sample_size); 637 setIntField(env, capabilities, "max_scan_reporting_threshold", c.max_scan_reporting_threshold); 638 setIntField(env, capabilities, "max_hotlist_bssids", c.max_hotlist_bssids); 639 setIntField(env, capabilities, "max_significant_wifi_change_aps", 640 c.max_significant_wifi_change_aps); 641 642 return JNI_TRUE; 643} 644 645 646static byte parseHexChar(char ch) { 647 if (isdigit(ch)) 648 return ch - '0'; 649 else if ('A' <= ch && ch <= 'F') 650 return ch - 'A' + 10; 651 else if ('a' <= ch && ch <= 'f') 652 return ch - 'a' + 10; 653 else { 654 ALOGE("invalid character in bssid %c", ch); 655 return 0; 656 } 657} 658 659static byte parseHexByte(const char * &str) { 660 byte b = parseHexChar(str[0]); 661 if (str[1] == ':' || str[1] == '\0') { 662 str += 2; 663 return b; 664 } else { 665 b = b << 4 | parseHexChar(str[1]); 666 str += 3; 667 return b; 668 } 669} 670 671static void parseMacAddress(const char *str, mac_addr addr) { 672 addr[0] = parseHexByte(str); 673 addr[1] = parseHexByte(str); 674 addr[2] = parseHexByte(str); 675 addr[3] = parseHexByte(str); 676 addr[4] = parseHexByte(str); 677 addr[5] = parseHexByte(str); 678} 679 680static bool parseMacAddress(JNIEnv *env, jobject obj, mac_addr addr) { 681 jstring macAddrString = (jstring) getObjectField( 682 env, obj, "bssid", "Ljava/lang/String;"); 683 684 if (macAddrString == NULL) { 685 ALOGE("Error getting bssid field"); 686 return false; 687 } 688 689 const char *bssid = env->GetStringUTFChars(macAddrString, NULL); 690 if (bssid == NULL) { 691 ALOGE("Error getting bssid"); 692 return false; 693 } 694 695 parseMacAddress(bssid, addr); 696 return true; 697} 698 699static void onHotlistApFound(wifi_request_id id, 700 unsigned num_results, wifi_scan_result *results) { 701 702 JNIEnv *env = NULL; 703 mVM->AttachCurrentThread(&env, NULL); 704 705 ALOGD("onHotlistApFound called, vm = %p, obj = %p, env = %p, num_results = %d", 706 mVM, mCls, env, num_results); 707 708 jclass clsScanResult = (env)->FindClass("android/net/wifi/ScanResult"); 709 if (clsScanResult == NULL) { 710 ALOGE("Error in accessing class"); 711 return; 712 } 713 714 jobjectArray scanResults = env->NewObjectArray(num_results, clsScanResult, NULL); 715 if (scanResults == NULL) { 716 ALOGE("Error in allocating array"); 717 return; 718 } 719 720 for (unsigned i = 0; i < num_results; i++) { 721 722 jobject scanResult = createObject(env, "android/net/wifi/ScanResult"); 723 if (scanResult == NULL) { 724 ALOGE("Error in creating scan result"); 725 return; 726 } 727 728 setStringField(env, scanResult, "SSID", results[i].ssid); 729 730 char bssid[32]; 731 sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", results[i].bssid[0], results[i].bssid[1], 732 results[i].bssid[2], results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]); 733 734 setStringField(env, scanResult, "BSSID", bssid); 735 736 setIntField(env, scanResult, "level", results[i].rssi); 737 setIntField(env, scanResult, "frequency", results[i].channel); 738 setLongField(env, scanResult, "timestamp", results[i].ts); 739 740 env->SetObjectArrayElement(scanResults, i, scanResult); 741 742 ALOGD("Found AP %32s %s", results[i].ssid, bssid); 743 } 744 745 reportEvent(env, mCls, "onHotlistApFound", "(I[Landroid/net/wifi/ScanResult;)V", 746 id, scanResults); 747} 748 749static void onHotlistApLost(wifi_request_id id, 750 unsigned num_results, wifi_scan_result *results) { 751 752 JNIEnv *env = NULL; 753 mVM->AttachCurrentThread(&env, NULL); 754 755 ALOGD("onHotlistApLost called, vm = %p, obj = %p, env = %p, num_results = %d", 756 mVM, mCls, env, num_results); 757 758 jclass clsScanResult = (env)->FindClass("android/net/wifi/ScanResult"); 759 if (clsScanResult == NULL) { 760 ALOGE("Error in accessing class"); 761 return; 762 } 763 764 jobjectArray scanResults = env->NewObjectArray(num_results, clsScanResult, NULL); 765 if (scanResults == NULL) { 766 ALOGE("Error in allocating array"); 767 return; 768 } 769 770 for (unsigned i = 0; i < num_results; i++) { 771 772 jobject scanResult = createObject(env, "android/net/wifi/ScanResult"); 773 if (scanResult == NULL) { 774 ALOGE("Error in creating scan result"); 775 return; 776 } 777 778 setStringField(env, scanResult, "SSID", results[i].ssid); 779 780 char bssid[32]; 781 sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", results[i].bssid[0], results[i].bssid[1], 782 results[i].bssid[2], results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]); 783 784 setStringField(env, scanResult, "BSSID", bssid); 785 786 setIntField(env, scanResult, "level", results[i].rssi); 787 setIntField(env, scanResult, "frequency", results[i].channel); 788 setLongField(env, scanResult, "timestamp", results[i].ts); 789 790 env->SetObjectArrayElement(scanResults, i, scanResult); 791 792 ALOGD("Lost AP %32s %s", results[i].ssid, bssid); 793 } 794 795 reportEvent(env, mCls, "onHotlistApLost", "(I[Landroid/net/wifi/ScanResult;)V", 796 id, scanResults); 797} 798 799 800static jboolean android_net_wifi_setHotlist( 801 JNIEnv *env, jclass cls, jint iface, jint id, jobject ap) { 802 803 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 804 ALOGD("setting hotlist on interface[%d] = %p", iface, handle); 805 806 wifi_bssid_hotlist_params params; 807 memset(¶ms, 0, sizeof(params)); 808 809 params.lost_ap_sample_size = getIntField(env, ap, "apLostThreshold"); 810 811 jobjectArray array = (jobjectArray) getObjectField(env, ap, 812 "bssidInfos", "[Landroid/net/wifi/WifiScanner$BssidInfo;"); 813 params.num_bssid = env->GetArrayLength(array); 814 815 if (params.num_bssid == 0) { 816 ALOGE("Error in accesing array"); 817 return false; 818 } 819 820 for (int i = 0; i < params.num_bssid; i++) { 821 jobject objAp = env->GetObjectArrayElement(array, i); 822 823 jstring macAddrString = (jstring) getObjectField( 824 env, objAp, "bssid", "Ljava/lang/String;"); 825 if (macAddrString == NULL) { 826 ALOGE("Error getting bssid field"); 827 return false; 828 } 829 830 const char *bssid = env->GetStringUTFChars(macAddrString, NULL); 831 if (bssid == NULL) { 832 ALOGE("Error getting bssid"); 833 return false; 834 } 835 parseMacAddress(bssid, params.ap[i].bssid); 836 837 mac_addr addr; 838 memcpy(addr, params.ap[i].bssid, sizeof(mac_addr)); 839 840 char bssidOut[32]; 841 sprintf(bssidOut, "%0x:%0x:%0x:%0x:%0x:%0x", addr[0], addr[1], 842 addr[2], addr[3], addr[4], addr[5]); 843 844 ALOGD("Added bssid %s", bssidOut); 845 846 params.ap[i].low = getIntField(env, objAp, "low"); 847 params.ap[i].high = getIntField(env, objAp, "high"); 848 } 849 850 wifi_hotlist_ap_found_handler handler; 851 memset(&handler, 0, sizeof(handler)); 852 853 handler.on_hotlist_ap_found = &onHotlistApFound; 854 handler.on_hotlist_ap_lost = &onHotlistApLost; 855 return hal_fn.wifi_set_bssid_hotlist(id, handle, params, handler) == WIFI_SUCCESS; 856} 857 858static jboolean android_net_wifi_resetHotlist( 859 JNIEnv *env, jclass cls, jint iface, jint id) { 860 861 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 862 ALOGD("resetting hotlist on interface[%d] = %p", iface, handle); 863 864 return hal_fn.wifi_reset_bssid_hotlist(id, handle) == WIFI_SUCCESS; 865} 866 867void onSignificantWifiChange(wifi_request_id id, 868 unsigned num_results, wifi_significant_change_result **results) { 869 JNIEnv *env = NULL; 870 mVM->AttachCurrentThread(&env, NULL); 871 872 ALOGD("onSignificantWifiChange called, vm = %p, obj = %p, env = %p", mVM, mCls, env); 873 874 jclass clsScanResult = (env)->FindClass("android/net/wifi/ScanResult"); 875 if (clsScanResult == NULL) { 876 ALOGE("Error in accessing class"); 877 return; 878 } 879 880 jobjectArray scanResults = env->NewObjectArray(num_results, clsScanResult, NULL); 881 if (scanResults == NULL) { 882 ALOGE("Error in allocating array"); 883 return; 884 } 885 886 for (unsigned i = 0; i < num_results; i++) { 887 888 wifi_significant_change_result &result = *(results[i]); 889 890 jobject scanResult = createObject(env, "android/net/wifi/ScanResult"); 891 if (scanResult == NULL) { 892 ALOGE("Error in creating scan result"); 893 return; 894 } 895 896 // setStringField(env, scanResult, "SSID", results[i].ssid); 897 898 char bssid[32]; 899 sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result.bssid[0], result.bssid[1], 900 result.bssid[2], result.bssid[3], result.bssid[4], result.bssid[5]); 901 902 setStringField(env, scanResult, "BSSID", bssid); 903 904 setIntField(env, scanResult, "level", result.rssi[0]); 905 setIntField(env, scanResult, "frequency", result.channel); 906 // setLongField(env, scanResult, "timestamp", result.ts); 907 908 env->SetObjectArrayElement(scanResults, i, scanResult); 909 } 910 911 reportEvent(env, mCls, "onSignificantWifiChange", "(I[Landroid/net/wifi/ScanResult;)V", 912 id, scanResults); 913 914} 915 916static jboolean android_net_wifi_trackSignificantWifiChange( 917 JNIEnv *env, jclass cls, jint iface, jint id, jobject settings) { 918 919 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 920 ALOGD("tracking significant wifi change on interface[%d] = %p", iface, handle); 921 922 wifi_significant_change_params params; 923 memset(¶ms, 0, sizeof(params)); 924 925 params.rssi_sample_size = getIntField(env, settings, "rssiSampleSize"); 926 params.lost_ap_sample_size = getIntField(env, settings, "lostApSampleSize"); 927 params.min_breaching = getIntField(env, settings, "minApsBreachingThreshold"); 928 929 const char *bssid_info_array_type = "[Landroid/net/wifi/WifiScanner$BssidInfo;"; 930 jobjectArray bssids = (jobjectArray)getObjectField( 931 env, settings, "bssidInfos", bssid_info_array_type); 932 params.num_bssid = env->GetArrayLength(bssids); 933 934 if (params.num_bssid == 0) { 935 ALOGE("Error in accessing array"); 936 return false; 937 } 938 939 ALOGD("Initialized common fields %d, %d, %d, %d", params.rssi_sample_size, 940 params.lost_ap_sample_size, params.min_breaching, params.num_bssid); 941 942 for (int i = 0; i < params.num_bssid; i++) { 943 jobject objAp = env->GetObjectArrayElement(bssids, i); 944 945 jstring macAddrString = (jstring) getObjectField( 946 env, objAp, "bssid", "Ljava/lang/String;"); 947 if (macAddrString == NULL) { 948 ALOGE("Error getting bssid field"); 949 return false; 950 } 951 952 const char *bssid = env->GetStringUTFChars(macAddrString, NULL); 953 if (bssid == NULL) { 954 ALOGE("Error getting bssid"); 955 return false; 956 } 957 958 mac_addr addr; 959 parseMacAddress(bssid, addr); 960 memcpy(params.ap[i].bssid, addr, sizeof(mac_addr)); 961 962 char bssidOut[32]; 963 sprintf(bssidOut, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], 964 addr[2], addr[3], addr[4], addr[5]); 965 966 params.ap[i].low = getIntField(env, objAp, "low"); 967 params.ap[i].high = getIntField(env, objAp, "high"); 968 969 ALOGD("Added bssid %s, [%04d, %04d]", bssidOut, params.ap[i].low, params.ap[i].high); 970 } 971 972 ALOGD("Added %d bssids", params.num_bssid); 973 974 wifi_significant_change_handler handler; 975 memset(&handler, 0, sizeof(handler)); 976 977 handler.on_significant_change = &onSignificantWifiChange; 978 return hal_fn.wifi_set_significant_change_handler(id, handle, params, handler) == WIFI_SUCCESS; 979} 980 981static jboolean android_net_wifi_untrackSignificantWifiChange( 982 JNIEnv *env, jclass cls, jint iface, jint id) { 983 984 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 985 ALOGD("resetting significant wifi change on interface[%d] = %p", iface, handle); 986 987 return hal_fn.wifi_reset_significant_change_handler(id, handle) == WIFI_SUCCESS; 988} 989 990wifi_iface_stat link_stat; 991wifi_radio_stat radio_stat; // L release has support for only one radio 992 993void onLinkStatsResults(wifi_request_id id, wifi_iface_stat *iface_stat, 994 int num_radios, wifi_radio_stat *radio_stats) 995{ 996 if (iface_stat != 0) { 997 memcpy(&link_stat, iface_stat, sizeof(wifi_iface_stat)); 998 } else { 999 memset(&link_stat, 0, sizeof(wifi_iface_stat)); 1000 } 1001 1002 if (num_radios > 0 && radio_stats != 0) { 1003 memcpy(&radio_stat, radio_stats, sizeof(wifi_radio_stat)); 1004 } else { 1005 memset(&radio_stat, 0, sizeof(wifi_radio_stat)); 1006 } 1007} 1008 1009static jobject android_net_wifi_getLinkLayerStats (JNIEnv *env, jclass cls, jint iface) { 1010 1011 wifi_stats_result_handler handler; 1012 memset(&handler, 0, sizeof(handler)); 1013 handler.on_link_stats_results = &onLinkStatsResults; 1014 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 1015 int result = hal_fn.wifi_get_link_stats(0, handle, handler); 1016 if (result < 0) { 1017 ALOGE("android_net_wifi_getLinkLayerStats: failed to get link statistics\n"); 1018 return NULL; 1019 } 1020 1021 jobject wifiLinkLayerStats = createObject(env, "android/net/wifi/WifiLinkLayerStats"); 1022 if (wifiLinkLayerStats == NULL) { 1023 ALOGE("Error in allocating wifiLinkLayerStats"); 1024 return NULL; 1025 } 1026 1027 setIntField(env, wifiLinkLayerStats, "beacon_rx", link_stat.beacon_rx); 1028 setIntField(env, wifiLinkLayerStats, "rssi_mgmt", link_stat.rssi_mgmt); 1029 setLongField(env, wifiLinkLayerStats, "rxmpdu_be", link_stat.ac[WIFI_AC_BE].rx_mpdu); 1030 setLongField(env, wifiLinkLayerStats, "rxmpdu_bk", link_stat.ac[WIFI_AC_BK].rx_mpdu); 1031 setLongField(env, wifiLinkLayerStats, "rxmpdu_vi", link_stat.ac[WIFI_AC_VI].rx_mpdu); 1032 setLongField(env, wifiLinkLayerStats, "rxmpdu_vo", link_stat.ac[WIFI_AC_VO].rx_mpdu); 1033 setLongField(env, wifiLinkLayerStats, "txmpdu_be", link_stat.ac[WIFI_AC_BE].tx_mpdu); 1034 setLongField(env, wifiLinkLayerStats, "txmpdu_bk", link_stat.ac[WIFI_AC_BK].tx_mpdu); 1035 setLongField(env, wifiLinkLayerStats, "txmpdu_vi", link_stat.ac[WIFI_AC_VI].tx_mpdu); 1036 setLongField(env, wifiLinkLayerStats, "txmpdu_vo", link_stat.ac[WIFI_AC_VO].tx_mpdu); 1037 setLongField(env, wifiLinkLayerStats, "lostmpdu_be", link_stat.ac[WIFI_AC_BE].mpdu_lost); 1038 setLongField(env, wifiLinkLayerStats, "lostmpdu_bk", link_stat.ac[WIFI_AC_BK].mpdu_lost); 1039 setLongField(env, wifiLinkLayerStats, "lostmpdu_vi", link_stat.ac[WIFI_AC_VI].mpdu_lost); 1040 setLongField(env, wifiLinkLayerStats, "lostmpdu_vo", link_stat.ac[WIFI_AC_VO].mpdu_lost); 1041 setLongField(env, wifiLinkLayerStats, "retries_be", link_stat.ac[WIFI_AC_BE].retries); 1042 setLongField(env, wifiLinkLayerStats, "retries_bk", link_stat.ac[WIFI_AC_BK].retries); 1043 setLongField(env, wifiLinkLayerStats, "retries_vi", link_stat.ac[WIFI_AC_VI].retries); 1044 setLongField(env, wifiLinkLayerStats, "retries_vo", link_stat.ac[WIFI_AC_VO].retries); 1045 1046 1047 setIntField(env, wifiLinkLayerStats, "on_time", radio_stat.on_time); 1048 setIntField(env, wifiLinkLayerStats, "tx_time", radio_stat.tx_time); 1049 setIntField(env, wifiLinkLayerStats, "rx_time", radio_stat.rx_time); 1050 setIntField(env, wifiLinkLayerStats, "on_time_scan", radio_stat.on_time_scan); 1051 1052 return wifiLinkLayerStats; 1053} 1054 1055static jint android_net_wifi_getSupportedFeatures(JNIEnv *env, jclass cls, jint iface) { 1056 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 1057 feature_set set = 0; 1058 1059 wifi_error result = WIFI_SUCCESS; 1060 /* 1061 set = WIFI_FEATURE_INFRA 1062 | WIFI_FEATURE_INFRA_5G 1063 | WIFI_FEATURE_HOTSPOT 1064 | WIFI_FEATURE_P2P 1065 | WIFI_FEATURE_SOFT_AP 1066 | WIFI_FEATURE_GSCAN 1067 | WIFI_FEATURE_PNO 1068 | WIFI_FEATURE_TDLS 1069 | WIFI_FEATURE_EPR; 1070 */ 1071 1072 result = hal_fn.wifi_get_supported_feature_set(handle, &set); 1073 if (result == WIFI_SUCCESS) { 1074 ALOGD("wifi_get_supported_feature_set returned set = 0x%x", set); 1075 return set; 1076 } else { 1077 ALOGD("wifi_get_supported_feature_set returned error = 0x%x", result); 1078 return 0; 1079 } 1080} 1081 1082static void onRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* results[]) { 1083 JNIEnv *env = NULL; 1084 mVM->AttachCurrentThread(&env, NULL); 1085 1086 ALOGD("onRttResults called, vm = %p, obj = %p, env = %p", mVM, mCls, env); 1087 1088 jclass clsRttResult = (env)->FindClass("android/net/wifi/RttManager$RttResult"); 1089 if (clsRttResult == NULL) { 1090 ALOGE("Error in accessing class"); 1091 return; 1092 } 1093 1094 jobjectArray rttResults = env->NewObjectArray(num_results, clsRttResult, NULL); 1095 if (rttResults == NULL) { 1096 ALOGE("Error in allocating array"); 1097 return; 1098 } 1099 1100 for (unsigned i = 0; i < num_results; i++) { 1101 1102 wifi_rtt_result *result = results[i]; 1103 1104 jobject rttResult = createObject(env, "android/net/wifi/RttManager$RttResult"); 1105 if (rttResult == NULL) { 1106 ALOGE("Error in creating rtt result"); 1107 return; 1108 } 1109 1110 char bssid[32]; 1111 sprintf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", result->addr[0], result->addr[1], 1112 result->addr[2], result->addr[3], result->addr[4], result->addr[5]); 1113 1114 setStringField(env, rttResult, "bssid", bssid); 1115 setIntField(env, rttResult, "burstNumber", result->burst_num); 1116 setIntField(env, rttResult, "measurementFrameNumber", result->measurement_number); 1117 setIntField(env, rttResult, "successMeasurementFrameNumber", result->success_number); 1118 setIntField(env, rttResult, "frameNumberPerBurstPeer", result->number_per_burst_peer); 1119 setIntField(env, rttResult, "status", result->status); 1120 setIntField(env, rttResult, "measurementType", result->type); 1121 setIntField(env, rttResult, "retryAfterDuration", result->retry_after_duration); 1122 setLongField(env, rttResult, "ts", result->ts); 1123 setIntField(env, rttResult, "rssi", result->rssi); 1124 setIntField(env, rttResult, "rssiSpread", result->rssi_spread); 1125 setIntField(env, rttResult, "txRate", result->tx_rate.bitrate); 1126 setIntField(env, rttResult, "rxRate", result->rx_rate.bitrate); 1127 setLongField(env, rttResult, "rtt", result->rtt); 1128 setLongField(env, rttResult, "rttStandardDeviation", result->rtt_sd); 1129 setIntField(env, rttResult, "distance", result->distance); 1130 setIntField(env, rttResult, "distanceStandardDeviation", result->distance_sd); 1131 setIntField(env, rttResult, "distanceSpread", result->distance_spread); 1132 setIntField(env, rttResult, "burstDuration", result->burst_duration); 1133 setIntField(env, rttResult, "negotiatedBurstNum", result->negotiated_burst_num); 1134 jobject LCI = createObject(env, "android/net/wifi/RttManager$WifiInformationElement"); 1135 if (result->LCI != NULL && result->LCI->len > 0) { 1136 ALOGD("Add LCI in result"); 1137 setByteField(env, LCI, "id", result->LCI->id); 1138 jbyteArray elements = env->NewByteArray(result->LCI->len); 1139 jbyte *bytes = (jbyte *)&(result->LCI->data[0]); 1140 env->SetByteArrayRegion(elements, 0, result->LCI->len, bytes); 1141 setObjectField(env, LCI, "data", "[B", elements); 1142 env->DeleteLocalRef(elements); 1143 } else { 1144 ALOGD("No LCI in result"); 1145 setByteField(env, LCI, "id", (byte)(0xff)); 1146 } 1147 setObjectField(env, rttResult, "LCI", 1148 "Landroid/net/wifi/RttManager$WifiInformationElement;", LCI); 1149 1150 jobject LCR = createObject(env, "android/net/wifi/RttManager$WifiInformationElement"); 1151 if (result->LCR != NULL && result->LCR->len > 0) { 1152 ALOGD("Add LCR in result"); 1153 setByteField(env, LCR, "id", result->LCR->id); 1154 jbyteArray elements = env->NewByteArray(result->LCI->len); 1155 jbyte *bytes = (jbyte *)&(result->LCR->data[0]); 1156 env->SetByteArrayRegion(elements, 0, result->LCI->len, bytes); 1157 setObjectField(env, LCR, "data", "[B", elements); 1158 env->DeleteLocalRef(elements); 1159 } else { 1160 ALOGD("No LCR in result"); 1161 setByteField(env, LCR, "id", (byte)(0xff)); 1162 } 1163 setObjectField(env, rttResult, "LCR", 1164 "Landroid/net/wifi/RttManager$WifiInformationElement;", LCR); 1165 1166 env->SetObjectArrayElement(rttResults, i, rttResult); 1167 env->DeleteLocalRef(LCI); 1168 env->DeleteLocalRef(LCR); 1169 env->DeleteLocalRef(rttResult); 1170 } 1171 1172 reportEvent(env, mCls, "onRttResults", "(I[Landroid/net/wifi/RttManager$RttResult;)V", 1173 id, rttResults); 1174 1175 //clean the local reference 1176 env->DeleteLocalRef(rttResults); 1177 env->DeleteLocalRef(clsRttResult); 1178 1179} 1180 1181const int MaxRttConfigs = 16; 1182 1183static jboolean android_net_wifi_requestRange( 1184 JNIEnv *env, jclass cls, jint iface, jint id, jobject params) { 1185 1186 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 1187 ALOGD("sending rtt request [%d] = %p", id, handle); 1188 1189 wifi_rtt_config configs[MaxRttConfigs]; 1190 memset(&configs, 0, sizeof(configs)); 1191 1192 int len = env->GetArrayLength((jobjectArray)params); 1193 if (len > MaxRttConfigs) { 1194 return false; 1195 } 1196 1197 for (int i = 0; i < len; i++) { 1198 1199 jobject param = env->GetObjectArrayElement((jobjectArray)params, i); 1200 if (param == NULL) { 1201 ALOGD("could not get element %d", i); 1202 continue; 1203 } 1204 1205 wifi_rtt_config &config = configs[i]; 1206 1207 parseMacAddress(env, param, config.addr); 1208 config.type = (wifi_rtt_type)getIntField(env, param, "requestType"); 1209 config.peer = (rtt_peer_type)getIntField(env, param, "deviceType"); 1210 config.channel.center_freq = getIntField(env, param, "frequency"); 1211 config.channel.width = (wifi_channel_width) getIntField(env, param, "channelWidth"); 1212 config.channel.center_freq0 = getIntField(env, param, "centerFreq0"); 1213 config.channel.center_freq1 = getIntField(env, param, "centerFreq1"); 1214 1215 config.num_burst = getIntField(env, param, "numberBurst"); 1216 config.burst_period = (unsigned) getIntField(env, param, "interval"); 1217 config.num_frames_per_burst = (unsigned) getIntField(env, param, "numSamplesPerBurst"); 1218 config.num_retries_per_rtt_frame = (unsigned) getIntField(env, param, 1219 "numRetriesPerMeasurementFrame"); 1220 config.num_retries_per_ftmr = (unsigned) getIntField(env, param, "numRetriesPerFTMR"); 1221 config.LCI_request = getBoolField(env, param, "LCIRequest") ? 1 : 0; 1222 config.LCR_request = getBoolField(env, param, "LCRRequest") ? 1 : 0; 1223 config.burst_duration = (unsigned) getIntField(env, param, "burstTimeout"); 1224 config.preamble = (wifi_rtt_preamble) getIntField(env, param, "preamble"); 1225 config.bw = (wifi_rtt_bw) getIntField(env, param, "bandwidth"); 1226 1227 ALOGD("RTT request destination %d: type is %d, peer is %d, bw is %d, center_freq is %d ", i, 1228 config.type,config.peer, config.channel.width, config.channel.center_freq0); 1229 ALOGD("center_freq0 is %d, center_freq1 is %d, num_burst is %d,interval is %d", 1230 config.channel.center_freq0, config.channel.center_freq1, config.num_burst, 1231 config.burst_period); 1232 ALOGD("frames_per_burst is %d, retries of measurement frame is %d, retries_per_ftmr is %d", 1233 config.num_frames_per_burst, config.num_retries_per_rtt_frame, 1234 config.num_retries_per_ftmr); 1235 ALOGD("LCI_requestis %d, LCR_request is %d, burst_timeout is %d, preamble is %d, bw is %d", 1236 config.LCI_request, config.LCR_request, config.burst_duration, config.preamble, 1237 config.bw); 1238 } 1239 1240 wifi_rtt_event_handler handler; 1241 handler.on_rtt_results = &onRttResults; 1242 1243 return hal_fn.wifi_rtt_range_request(id, handle, len, configs, handler) == WIFI_SUCCESS; 1244} 1245 1246static jboolean android_net_wifi_cancelRange( 1247 JNIEnv *env, jclass cls, jint iface, jint id, jobject params) { 1248 1249 wifi_interface_handle handle = getIfaceHandle(env, 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 = env->GetArrayLength((jobjectArray)params); 1256 if (len > MaxRttConfigs) { 1257 return false; 1258 } 1259 1260 for (int i = 0; i < len; i++) { 1261 1262 jobject param = env->GetObjectArrayElement((jobjectArray)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 1274static jboolean android_net_wifi_setScanningMacOui(JNIEnv *env, jclass cls, 1275 jint iface, jbyteArray param) { 1276 1277 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 1278 ALOGD("setting scan oui %p", handle); 1279 1280 static const unsigned oui_len = 3; /* OUI is upper 3 bytes of mac_address */ 1281 int len = env->GetArrayLength(param); 1282 if (len != oui_len) { 1283 ALOGE("invalid oui length %d", len); 1284 return false; 1285 } 1286 1287 jbyte* bytes = env->GetByteArrayElements(param, NULL); 1288 if (bytes == NULL) { 1289 ALOGE("failed to get array"); 1290 return false; 1291 } 1292 1293 return hal_fn.wifi_set_scanning_mac_oui(handle, (byte *)bytes) == WIFI_SUCCESS; 1294} 1295 1296static jintArray android_net_wifi_getValidChannels(JNIEnv *env, jclass cls, 1297 jint iface, jint band) { 1298 1299 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 1300 ALOGD("getting valid channels %p", handle); 1301 1302 static const int MaxChannels = 64; 1303 wifi_channel channels[64]; 1304 int num_channels = 0; 1305 wifi_error result = hal_fn.wifi_get_valid_channels(handle, band, MaxChannels, 1306 channels, &num_channels); 1307 1308 if (result == WIFI_SUCCESS) { 1309 jintArray channelArray = env->NewIntArray(num_channels); 1310 if (channelArray == NULL) { 1311 ALOGE("failed to allocate channel list"); 1312 return NULL; 1313 } 1314 1315 env->SetIntArrayRegion(channelArray, 0, num_channels, channels); 1316 return channelArray; 1317 } else { 1318 ALOGE("failed to get channel list : %d", result); 1319 return NULL; 1320 } 1321} 1322 1323static jboolean android_net_wifi_setDfsFlag(JNIEnv *env, jclass cls, jint iface, jboolean dfs) { 1324 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 1325 ALOGD("setting dfs flag to %s, %p", dfs ? "true" : "false", handle); 1326 1327 u32 nodfs = dfs ? 0 : 1; 1328 wifi_error result = hal_fn.wifi_set_nodfs_flag(handle, nodfs); 1329 return result == WIFI_SUCCESS; 1330} 1331 1332static jobject android_net_wifi_get_rtt_capabilities(JNIEnv *env, jclass cls, jint iface) { 1333 wifi_rtt_capabilities rtt_capabilities; 1334 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 1335 wifi_error ret = hal_fn.wifi_get_rtt_capabilities(handle, &rtt_capabilities); 1336 1337 if(WIFI_SUCCESS == ret) { 1338 jobject capabilities = createObject(env, "android/net/wifi/RttManager$RttCapabilities"); 1339 setBooleanField(env, capabilities, "oneSidedRttSupported", 1340 rtt_capabilities.rtt_one_sided_supported == 1); 1341 setBooleanField(env, capabilities, "twoSided11McRttSupported", 1342 rtt_capabilities.rtt_ftm_supported == 1); 1343 setBooleanField(env, capabilities, "lciSupported", 1344 rtt_capabilities.lci_support); 1345 setBooleanField(env,capabilities, "lcrSupported", 1346 rtt_capabilities.lcr_support); 1347 setIntField(env, capabilities, "preambleSupported", 1348 rtt_capabilities.preamble_support); 1349 setIntField(env, capabilities, "bwSupported", 1350 rtt_capabilities.bw_support); 1351 ALOGD("One side RTT is: %s", rtt_capabilities.rtt_one_sided_supported ==1 ? "support" : 1352 "not support"); 1353 ALOGD("Two side RTT is: %s", rtt_capabilities.rtt_ftm_supported == 1 ? "support" : 1354 "not support"); 1355 ALOGD("LCR is: %s", rtt_capabilities.lcr_support == 1 ? "support" : "not support"); 1356 1357 ALOGD("LCI is: %s", rtt_capabilities.lci_support == 1 ? "support" : "not support"); 1358 1359 ALOGD("Support Preamble is : %d support BW is %d", rtt_capabilities.preamble_support, 1360 rtt_capabilities.bw_support); 1361 return capabilities; 1362 } else { 1363 return NULL; 1364 } 1365} 1366 1367static jboolean android_net_wifi_set_Country_Code_Hal(JNIEnv *env,jclass cls, jint iface, 1368 jstring country_code) { 1369 1370 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 1371 const char *country = env->GetStringUTFChars(country_code, NULL); 1372 1373 ALOGD("set country code: %s", country); 1374 wifi_error res = hal_fn.wifi_set_country_code(handle, country); 1375 env->ReleaseStringUTFChars(country_code, country); 1376 1377 return res == WIFI_SUCCESS; 1378} 1379// ---------------------------------------------------------------------------- 1380// Debug framework 1381// ---------------------------------------------------------------------------- 1382 1383static void onRingBufferData(char * ring_name, char * buffer, 1384int buffer_size, wifi_ring_buffer_status *status) { 1385 JNIEnv *env = NULL; 1386 mVM->AttachCurrentThread(&env, NULL); 1387 1388 ALOGD("onRingBufferData called, vm = %p, obj = %p, env = %p", mVM, mCls, env); 1389 1390 reportEvent(env, mCls, "onDataAvailable", "(I[Landroid/net/wifi/WiFiLogger$LogData;)V", 1391 0, 0); 1392} 1393 1394static jboolean android_net_wifi_start_logging(JNIEnv *env, jclass cls, jint iface) { 1395 1396 wifi_interface_handle handle = getIfaceHandle(env, cls, iface); 1397 ALOGD("android_net_wifi_start_logging = %p", handle); 1398 1399 if (handle == 0) { 1400 return WIFI_ERROR_UNINITIALIZED; 1401 } 1402 wifi_ring_buffer_data_handler handler; 1403 handler.on_ring_buffer_data = &onRingBufferData; 1404 1405 wifi_error result = WIFI_SUCCESS; //ifi_start_logging(handle, 1, 0, 5, 4*1024,(u8*)"wifi_connectivity_events", handler); 1406 1407 return result; 1408} 1409 1410 1411// ---------------------------------------------------------------------------- 1412 1413/* 1414 * JNI registration. 1415 */ 1416static JNINativeMethod gWifiMethods[] = { 1417 /* name, signature, funcPtr */ 1418 1419 { "loadDriver", "()Z", (void *)android_net_wifi_loadDriver }, 1420 { "isDriverLoaded", "()Z", (void *)android_net_wifi_isDriverLoaded }, 1421 { "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver }, 1422 { "startSupplicant", "(Z)Z", (void *)android_net_wifi_startSupplicant }, 1423 { "killSupplicant", "(Z)Z", (void *)android_net_wifi_killSupplicant }, 1424 { "connectToSupplicantNative", "()Z", (void *)android_net_wifi_connectToSupplicant }, 1425 { "closeSupplicantConnectionNative", "()V", 1426 (void *)android_net_wifi_closeSupplicantConnection }, 1427 { "waitForEventNative", "()Ljava/lang/String;", (void*)android_net_wifi_waitForEvent }, 1428 { "doBooleanCommandNative", "(Ljava/lang/String;)Z", (void*)android_net_wifi_doBooleanCommand }, 1429 { "doIntCommandNative", "(Ljava/lang/String;)I", (void*)android_net_wifi_doIntCommand }, 1430 { "doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;", 1431 (void*) android_net_wifi_doStringCommand }, 1432 { "startHalNative", "()Z", (void*) android_net_wifi_startHal }, 1433 { "stopHalNative", "()V", (void*) android_net_wifi_stopHal }, 1434 { "waitForHalEventNative", "()V", (void*) android_net_wifi_waitForHalEvents }, 1435 { "getInterfacesNative", "()I", (void*) android_net_wifi_getInterfaces}, 1436 { "getInterfaceNameNative", "(I)Ljava/lang/String;", (void*) android_net_wifi_getInterfaceName}, 1437 { "getScanCapabilitiesNative", "(ILcom/android/server/wifi/WifiNative$ScanCapabilities;)Z", 1438 (void *) android_net_wifi_getScanCapabilities}, 1439 { "startScanNative", "(IILcom/android/server/wifi/WifiNative$ScanSettings;)Z", 1440 (void*) android_net_wifi_startScan}, 1441 { "stopScanNative", "(II)Z", (void*) android_net_wifi_stopScan}, 1442 { "getScanResultsNative", "(IZ)[Landroid/net/wifi/WifiScanner$ScanData;", 1443 (void *) android_net_wifi_getScanResults}, 1444 { "setHotlistNative", "(IILandroid/net/wifi/WifiScanner$HotlistSettings;)Z", 1445 (void*) android_net_wifi_setHotlist}, 1446 { "resetHotlistNative", "(II)Z", (void*) android_net_wifi_resetHotlist}, 1447 { "trackSignificantWifiChangeNative", "(IILandroid/net/wifi/WifiScanner$WifiChangeSettings;)Z", 1448 (void*) android_net_wifi_trackSignificantWifiChange}, 1449 { "untrackSignificantWifiChangeNative", "(II)Z", 1450 (void*) android_net_wifi_untrackSignificantWifiChange}, 1451 { "getWifiLinkLayerStatsNative", "(I)Landroid/net/wifi/WifiLinkLayerStats;", 1452 (void*) android_net_wifi_getLinkLayerStats}, 1453 { "getSupportedFeatureSetNative", "(I)I", 1454 (void*) android_net_wifi_getSupportedFeatures}, 1455 { "requestRangeNative", "(II[Landroid/net/wifi/RttManager$RttParams;)Z", 1456 (void*) android_net_wifi_requestRange}, 1457 { "cancelRangeRequestNative", "(II[Landroid/net/wifi/RttManager$RttParams;)Z", 1458 (void*) android_net_wifi_cancelRange}, 1459 { "setScanningMacOuiNative", "(I[B)Z", (void*) android_net_wifi_setScanningMacOui}, 1460 { "getChannelsForBandNative", "(II)[I", (void*) android_net_wifi_getValidChannels}, 1461 { "setDfsFlagNative", "(IZ)Z", (void*) android_net_wifi_setDfsFlag}, 1462 { "toggleInterfaceNative", "(I)Z", (void*) android_net_wifi_toggle_interface}, 1463 { "getRttCapabilitiesNative", "(I)Landroid/net/wifi/RttManager$RttCapabilities;", 1464 (void*) android_net_wifi_get_rtt_capabilities}, 1465 { "startLogging", "(I)Z", (void*) android_net_wifi_start_logging}, 1466 {"setCountryCodeHalNative", "(ILjava/lang/String;)Z", 1467 (void*) android_net_wifi_set_Country_Code_Hal} 1468}; 1469 1470int register_android_net_wifi_WifiNative(JNIEnv* env) { 1471 return AndroidRuntime::registerNativeMethods(env, 1472 "com/android/server/wifi/WifiNative", gWifiMethods, NELEM(gWifiMethods)); 1473} 1474 1475 1476/* User to register native functions */ 1477extern "C" 1478jint Java_com_android_server_wifi_WifiNative_registerNatives(JNIEnv* env, jclass clazz) { 1479 return AndroidRuntime::registerNativeMethods(env, 1480 "com/android/server/wifi/WifiNative", gWifiMethods, NELEM(gWifiMethods)); 1481} 1482 1483}; // namespace android 1484