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