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