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