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 26 #include "wifi.h" 27 28 #define WIFI_PKG_NAME "android/net/wifi/WifiNative" 29 #define BUF_SIZE 256 30 31 //TODO: This file can be refactored to push a lot of the functionality to java 32 //with just a few JNI calls - doBoolean/doInt/doString 33 34 namespace android { 35 36 static jboolean sScanModeActive = false; 37 38 static int doCommand(const char *cmd, char *replybuf, int replybuflen) 39 { 40 size_t reply_len = replybuflen - 1; 41 42 if (::wifi_command(cmd, replybuf, &reply_len) != 0) 43 return -1; 44 else { 45 // Strip off trailing newline 46 if (reply_len > 0 && replybuf[reply_len-1] == '\n') 47 replybuf[reply_len-1] = '\0'; 48 else 49 replybuf[reply_len] = '\0'; 50 return 0; 51 } 52 } 53 54 static jint doIntCommand(const char* fmt, ...) 55 { 56 char buf[BUF_SIZE]; 57 va_list args; 58 va_start(args, fmt); 59 int byteCount = vsnprintf(buf, sizeof(buf), fmt, args); 60 va_end(args); 61 if (byteCount < 0 || byteCount >= BUF_SIZE) { 62 return -1; 63 } 64 char reply[BUF_SIZE]; 65 if (doCommand(buf, reply, sizeof(reply)) != 0) { 66 return -1; 67 } 68 return static_cast<jint>(atoi(reply)); 69 } 70 71 static jboolean doBooleanCommand(const char* expect, const char* fmt, ...) 72 { 73 char buf[BUF_SIZE]; 74 va_list args; 75 va_start(args, fmt); 76 int byteCount = vsnprintf(buf, sizeof(buf), fmt, args); 77 va_end(args); 78 if (byteCount < 0 || byteCount >= BUF_SIZE) { 79 return JNI_FALSE; 80 } 81 char reply[BUF_SIZE]; 82 if (doCommand(buf, reply, sizeof(reply)) != 0) { 83 return JNI_FALSE; 84 } 85 return (strcmp(reply, expect) == 0); 86 } 87 88 // Send a command to the supplicant, and return the reply as a String 89 static jstring doStringCommand(JNIEnv* env, const char* fmt, ...) { 90 char buf[BUF_SIZE]; 91 va_list args; 92 va_start(args, fmt); 93 int byteCount = vsnprintf(buf, sizeof(buf), fmt, args); 94 va_end(args); 95 if (byteCount < 0 || byteCount >= BUF_SIZE) { 96 return NULL; 97 } 98 char reply[4096]; 99 if (doCommand(buf, reply, sizeof(reply)) != 0) { 100 return NULL; 101 } 102 // TODO: why not just NewStringUTF? 103 String16 str((char *)reply); 104 return env->NewString((const jchar *)str.string(), str.size()); 105 } 106 107 static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject) 108 { 109 return (jboolean)(::is_wifi_driver_loaded() == 1); 110 } 111 112 static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject) 113 { 114 return (jboolean)(::wifi_load_driver() == 0); 115 } 116 117 static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject) 118 { 119 return (jboolean)(::wifi_unload_driver() == 0); 120 } 121 122 static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject) 123 { 124 return (jboolean)(::wifi_start_supplicant() == 0); 125 } 126 127 static jboolean android_net_wifi_startP2pSupplicant(JNIEnv* env, jobject) 128 { 129 return (jboolean)(::wifi_start_p2p_supplicant() == 0); 130 } 131 132 static jboolean android_net_wifi_stopSupplicant(JNIEnv* env, jobject) 133 { 134 return doBooleanCommand("OK", "TERMINATE"); 135 } 136 137 static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject) 138 { 139 return (jboolean)(::wifi_stop_supplicant() == 0); 140 } 141 142 static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject) 143 { 144 return (jboolean)(::wifi_connect_to_supplicant() == 0); 145 } 146 147 static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject) 148 { 149 ::wifi_close_supplicant_connection(); 150 } 151 152 static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject) 153 { 154 char buf[BUF_SIZE]; 155 156 int nread = ::wifi_wait_for_event(buf, sizeof buf); 157 if (nread > 0) { 158 return env->NewStringUTF(buf); 159 } else { 160 return NULL; 161 } 162 } 163 164 static jstring android_net_wifi_listNetworksCommand(JNIEnv* env, jobject) 165 { 166 return doStringCommand(env, "LIST_NETWORKS"); 167 } 168 169 static jint android_net_wifi_addNetworkCommand(JNIEnv* env, jobject) 170 { 171 return doIntCommand("ADD_NETWORK"); 172 } 173 174 static jboolean android_net_wifi_wpsPbcCommand(JNIEnv* env, jobject, jstring javaBssid) 175 { 176 ScopedUtfChars bssid(env, javaBssid); 177 if (bssid.c_str() == NULL) { 178 return JNI_FALSE; 179 } 180 return doBooleanCommand("OK", "WPS_PBC %s", bssid.c_str()); 181 } 182 183 static jboolean android_net_wifi_wpsPinFromAccessPointCommand(JNIEnv* env, jobject, 184 jstring javaBssid, jstring javaApPin) 185 { 186 ScopedUtfChars bssid(env, javaBssid); 187 if (bssid.c_str() == NULL) { 188 return JNI_FALSE; 189 } 190 ScopedUtfChars apPin(env, javaApPin); 191 if (apPin.c_str() == NULL) { 192 return JNI_FALSE; 193 } 194 return doBooleanCommand("OK", "WPS_REG %s %s", bssid.c_str(), apPin.c_str()); 195 } 196 197 static jstring android_net_wifi_wpsPinFromDeviceCommand(JNIEnv* env, jobject, jstring javaBssid) 198 { 199 ScopedUtfChars bssid(env, javaBssid); 200 if (bssid.c_str() == NULL) { 201 return NULL; 202 } 203 return doStringCommand(env, "WPS_PIN %s", bssid.c_str()); 204 } 205 206 static jboolean android_net_wifi_setCountryCodeCommand(JNIEnv* env, jobject, jstring javaCountry) 207 { 208 ScopedUtfChars country(env, javaCountry); 209 if (country.c_str() == NULL) { 210 return JNI_FALSE; 211 } 212 return doBooleanCommand("OK", "DRIVER COUNTRY %s", country.c_str()); 213 } 214 215 static jboolean android_net_wifi_setNetworkVariableCommand(JNIEnv* env, 216 jobject, 217 jint netId, 218 jstring javaName, 219 jstring javaValue) 220 { 221 ScopedUtfChars name(env, javaName); 222 if (name.c_str() == NULL) { 223 return JNI_FALSE; 224 } 225 ScopedUtfChars value(env, javaValue); 226 if (value.c_str() == NULL) { 227 return JNI_FALSE; 228 } 229 return doBooleanCommand("OK", "SET_NETWORK %d %s %s", netId, name.c_str(), value.c_str()); 230 } 231 232 static jstring android_net_wifi_getNetworkVariableCommand(JNIEnv* env, 233 jobject, 234 jint netId, 235 jstring javaName) 236 { 237 ScopedUtfChars name(env, javaName); 238 if (name.c_str() == NULL) { 239 return NULL; 240 } 241 return doStringCommand(env, "GET_NETWORK %d %s", netId, name.c_str()); 242 } 243 244 static jboolean android_net_wifi_removeNetworkCommand(JNIEnv* env, jobject, jint netId) 245 { 246 return doBooleanCommand("OK", "REMOVE_NETWORK %d", netId); 247 } 248 249 static jboolean android_net_wifi_enableNetworkCommand(JNIEnv* env, 250 jobject, 251 jint netId, 252 jboolean disableOthers) 253 { 254 return doBooleanCommand("OK", "%s_NETWORK %d", disableOthers ? "SELECT" : "ENABLE", netId); 255 } 256 257 static jboolean android_net_wifi_disableNetworkCommand(JNIEnv* env, jobject, jint netId) 258 { 259 return doBooleanCommand("OK", "DISABLE_NETWORK %d", netId); 260 } 261 262 static jstring android_net_wifi_statusCommand(JNIEnv* env, jobject) 263 { 264 return doStringCommand(env, "STATUS"); 265 } 266 267 static jboolean android_net_wifi_pingCommand(JNIEnv* env, jobject) 268 { 269 return doBooleanCommand("PONG", "PING"); 270 } 271 272 static jstring android_net_wifi_scanResultsCommand(JNIEnv* env, jobject) 273 { 274 return doStringCommand(env, "SCAN_RESULTS"); 275 } 276 277 static jboolean android_net_wifi_disconnectCommand(JNIEnv* env, jobject) 278 { 279 return doBooleanCommand("OK", "DISCONNECT"); 280 } 281 282 static jboolean android_net_wifi_reconnectCommand(JNIEnv* env, jobject) 283 { 284 return doBooleanCommand("OK", "RECONNECT"); 285 } 286 static jboolean android_net_wifi_reassociateCommand(JNIEnv* env, jobject) 287 { 288 return doBooleanCommand("OK", "REASSOCIATE"); 289 } 290 291 static jboolean doSetScanMode(jboolean setActive) 292 { 293 return doBooleanCommand("OK", (setActive ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE")); 294 } 295 296 static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject, jboolean forceActive) 297 { 298 jboolean result; 299 300 // Ignore any error from setting the scan mode. 301 // The scan will still work. 302 if (forceActive && !sScanModeActive) 303 doSetScanMode(true); 304 result = doBooleanCommand("OK", "SCAN"); 305 if (forceActive && !sScanModeActive) 306 doSetScanMode(sScanModeActive); 307 return result; 308 } 309 310 static jboolean android_net_wifi_setScanModeCommand(JNIEnv* env, jobject, jboolean setActive) 311 { 312 sScanModeActive = setActive; 313 return doSetScanMode(setActive); 314 } 315 316 static jboolean android_net_wifi_startDriverCommand(JNIEnv* env, jobject) 317 { 318 return doBooleanCommand("OK", "DRIVER START"); 319 } 320 321 static jboolean android_net_wifi_stopDriverCommand(JNIEnv* env, jobject) 322 { 323 return doBooleanCommand("OK", "DRIVER STOP"); 324 } 325 326 /* 327 Multicast filtering rules work as follows: 328 329 The driver can filter multicast (v4 and/or v6) and broadcast packets when in 330 a power optimized mode (typically when screen goes off). 331 332 In order to prevent the driver from filtering the multicast/broadcast packets, we have to 333 add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective 334 335 DRIVER RXFILTER-ADD Num 336 where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6 337 338 and DRIVER RXFILTER-START 339 340 In order to stop the usage of these rules, we do 341 342 DRIVER RXFILTER-STOP 343 DRIVER RXFILTER-REMOVE Num 344 where Num is as described for RXFILTER-ADD 345 346 The SETSUSPENDOPT driver command overrides the filtering rules 347 */ 348 349 static jboolean android_net_wifi_startMultiV4Filtering(JNIEnv* env, jobject) 350 { 351 return doBooleanCommand("OK", "DRIVER RXFILTER-STOP") 352 && doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 2") 353 && doBooleanCommand("OK", "DRIVER RXFILTER-START"); 354 } 355 356 static jboolean android_net_wifi_stopMultiV4Filtering(JNIEnv* env, jobject) 357 { 358 return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 2") 359 && doBooleanCommand("OK", "DRIVER RXFILTER-START"); 360 } 361 362 static jboolean android_net_wifi_startMultiV6Filtering(JNIEnv* env, jobject) 363 { 364 return doBooleanCommand("OK", "DRIVER RXFILTER-STOP") 365 && doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 3") 366 && doBooleanCommand("OK", "DRIVER RXFILTER-START"); 367 } 368 369 static jboolean android_net_wifi_stopMultiV6Filtering(JNIEnv* env, jobject) 370 { 371 return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 3") 372 && doBooleanCommand("OK", "DRIVER RXFILTER-START"); 373 } 374 375 376 static jint android_net_wifi_getRssiHelper(const char *cmd) 377 { 378 char reply[BUF_SIZE]; 379 int rssi = -200; 380 381 if (doCommand(cmd, reply, sizeof(reply)) != 0) { 382 return (jint)-1; 383 } 384 385 // reply comes back in the form "<SSID> rssi XX" where XX is the 386 // number we're interested in. if we're associating, it returns "OK". 387 // beware - <SSID> can contain spaces. 388 if (strcmp(reply, "OK") != 0) { 389 // beware of trailing spaces 390 char* end = reply + strlen(reply); 391 while (end > reply && end[-1] == ' ') { 392 end--; 393 } 394 *end = 0; 395 396 char* lastSpace = strrchr(reply, ' '); 397 // lastSpace should be preceded by "rssi" and followed by the value 398 if (lastSpace && !strncasecmp(lastSpace - 4, "rssi", 4)) { 399 sscanf(lastSpace + 1, "%d", &rssi); 400 } 401 } 402 return (jint)rssi; 403 } 404 405 static jstring android_net_wifi_getMacAddressCommand(JNIEnv* env, jobject) 406 { 407 char reply[BUF_SIZE]; 408 char buf[BUF_SIZE]; 409 410 if (doCommand("DRIVER MACADDR", reply, sizeof(reply)) != 0) { 411 return NULL; 412 } 413 // reply comes back in the form "Macaddr = XX.XX.XX.XX.XX.XX" where XX 414 // is the part of the string we're interested in. 415 if (sscanf(reply, "%*s = %255s", buf) == 1) { 416 return env->NewStringUTF(buf); 417 } 418 return NULL; 419 } 420 421 static jboolean android_net_wifi_setPowerModeCommand(JNIEnv* env, jobject, jint mode) 422 { 423 return doBooleanCommand("OK", "DRIVER POWERMODE %d", mode); 424 } 425 426 static jint android_net_wifi_getPowerModeCommand(JNIEnv* env, jobject) 427 { 428 char reply[BUF_SIZE]; 429 int power; 430 431 if (doCommand("DRIVER GETPOWER", reply, sizeof(reply)) != 0) { 432 return (jint)-1; 433 } 434 // reply comes back in the form "powermode = XX" where XX is the 435 // number we're interested in. 436 if (sscanf(reply, "%*s = %u", &power) != 1) { 437 return (jint)-1; 438 } 439 return (jint)power; 440 } 441 442 static jboolean android_net_wifi_setBandCommand(JNIEnv* env, jobject, jint band) 443 { 444 return doBooleanCommand("OK", "DRIVER SETBAND %d", band); 445 } 446 447 static jint android_net_wifi_getBandCommand(JNIEnv* env, jobject) 448 { 449 char reply[25]; 450 int band; 451 452 if (doCommand("DRIVER GETBAND", reply, sizeof(reply)) != 0) { 453 return (jint)-1; 454 } 455 // reply comes back in the form "Band X" where X is the 456 // number we're interested in. 457 sscanf(reply, "%*s %u", &band); 458 return (jint)band; 459 } 460 461 static jboolean android_net_wifi_setBluetoothCoexistenceModeCommand(JNIEnv* env, jobject, jint mode) 462 { 463 return doBooleanCommand("OK", "DRIVER BTCOEXMODE %d", mode); 464 } 465 466 static jboolean android_net_wifi_setBluetoothCoexistenceScanModeCommand(JNIEnv* env, jobject, jboolean setCoexScanMode) 467 { 468 return doBooleanCommand("OK", "DRIVER BTCOEXSCAN-%s", setCoexScanMode ? "START" : "STOP"); 469 } 470 471 static jboolean android_net_wifi_saveConfigCommand(JNIEnv* env, jobject) 472 { 473 // Make sure we never write out a value for AP_SCAN other than 1 474 (void)doBooleanCommand("OK", "AP_SCAN 1"); 475 return doBooleanCommand("OK", "SAVE_CONFIG"); 476 } 477 478 static jboolean android_net_wifi_reloadConfigCommand(JNIEnv* env, jobject) 479 { 480 return doBooleanCommand("OK", "RECONFIGURE"); 481 } 482 483 static jboolean android_net_wifi_setScanResultHandlingCommand(JNIEnv* env, jobject, jint mode) 484 { 485 return doBooleanCommand("OK", "AP_SCAN %d", mode); 486 } 487 488 static jboolean android_net_wifi_addToBlacklistCommand(JNIEnv* env, jobject, jstring javaBssid) 489 { 490 ScopedUtfChars bssid(env, javaBssid); 491 if (bssid.c_str() == NULL) { 492 return JNI_FALSE; 493 } 494 return doBooleanCommand("OK", "BLACKLIST %s", bssid.c_str()); 495 } 496 497 static jboolean android_net_wifi_clearBlacklistCommand(JNIEnv* env, jobject) 498 { 499 return doBooleanCommand("OK", "BLACKLIST clear"); 500 } 501 502 static jboolean android_net_wifi_setSuspendOptimizationsCommand(JNIEnv* env, jobject, jboolean enabled) 503 { 504 return doBooleanCommand("OK", "DRIVER SETSUSPENDOPT %d", enabled ? 0 : 1); 505 } 506 507 static void android_net_wifi_enableBackgroundScanCommand(JNIEnv* env, jobject, jboolean enable) 508 { 509 //Note: BGSCAN-START and BGSCAN-STOP are documented in core/res/res/values/config.xml 510 //and will need an update if the names are changed 511 if (enable) { 512 doBooleanCommand("OK", "DRIVER BGSCAN-START"); 513 } else { 514 doBooleanCommand("OK", "DRIVER BGSCAN-STOP"); 515 } 516 } 517 518 static void android_net_wifi_setScanIntervalCommand(JNIEnv* env, jobject, jint scanInterval) 519 { 520 doBooleanCommand("OK", "SCAN_INTERVAL %d", scanInterval); 521 } 522 523 524 static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring javaCommand) 525 { 526 ScopedUtfChars command(env, javaCommand); 527 if (command.c_str() == NULL) { 528 return JNI_FALSE; 529 } 530 return doBooleanCommand("OK", "%s", command.c_str()); 531 } 532 533 static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring javaCommand) 534 { 535 ScopedUtfChars command(env, javaCommand); 536 if (command.c_str() == NULL) { 537 return -1; 538 } 539 return doIntCommand("%s", command.c_str()); 540 } 541 542 static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring javaCommand) 543 { 544 ScopedUtfChars command(env, javaCommand); 545 if (command.c_str() == NULL) { 546 return NULL; 547 } 548 return doStringCommand(env, "%s", command.c_str()); 549 } 550 551 552 553 // ---------------------------------------------------------------------------- 554 555 /* 556 * JNI registration. 557 */ 558 static JNINativeMethod gWifiMethods[] = { 559 /* name, signature, funcPtr */ 560 561 { "loadDriver", "()Z", (void *)android_net_wifi_loadDriver }, 562 { "isDriverLoaded", "()Z", (void *)android_net_wifi_isDriverLoaded}, 563 { "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver }, 564 { "startSupplicant", "()Z", (void *)android_net_wifi_startSupplicant }, 565 { "startP2pSupplicant", "()Z", (void *)android_net_wifi_startP2pSupplicant }, 566 { "stopSupplicant", "()Z", (void*) android_net_wifi_stopSupplicant }, 567 { "killSupplicant", "()Z", (void *)android_net_wifi_killSupplicant }, 568 { "connectToSupplicant", "()Z", (void *)android_net_wifi_connectToSupplicant }, 569 { "closeSupplicantConnection", "()V", (void *)android_net_wifi_closeSupplicantConnection }, 570 571 { "listNetworksCommand", "()Ljava/lang/String;", 572 (void*) android_net_wifi_listNetworksCommand }, 573 { "addNetworkCommand", "()I", (void*) android_net_wifi_addNetworkCommand }, 574 { "setNetworkVariableCommand", "(ILjava/lang/String;Ljava/lang/String;)Z", 575 (void*) android_net_wifi_setNetworkVariableCommand }, 576 { "getNetworkVariableCommand", "(ILjava/lang/String;)Ljava/lang/String;", 577 (void*) android_net_wifi_getNetworkVariableCommand }, 578 { "removeNetworkCommand", "(I)Z", (void*) android_net_wifi_removeNetworkCommand }, 579 { "enableNetworkCommand", "(IZ)Z", (void*) android_net_wifi_enableNetworkCommand }, 580 { "disableNetworkCommand", "(I)Z", (void*) android_net_wifi_disableNetworkCommand }, 581 { "waitForEvent", "()Ljava/lang/String;", (void*) android_net_wifi_waitForEvent }, 582 { "statusCommand", "()Ljava/lang/String;", (void*) android_net_wifi_statusCommand }, 583 { "scanResultsCommand", "()Ljava/lang/String;", (void*) android_net_wifi_scanResultsCommand }, 584 { "pingCommand", "()Z", (void *)android_net_wifi_pingCommand }, 585 { "disconnectCommand", "()Z", (void *)android_net_wifi_disconnectCommand }, 586 { "reconnectCommand", "()Z", (void *)android_net_wifi_reconnectCommand }, 587 { "reassociateCommand", "()Z", (void *)android_net_wifi_reassociateCommand }, 588 { "scanCommand", "(Z)Z", (void*) android_net_wifi_scanCommand }, 589 { "setScanModeCommand", "(Z)Z", (void*) android_net_wifi_setScanModeCommand }, 590 { "startDriverCommand", "()Z", (void*) android_net_wifi_startDriverCommand }, 591 { "stopDriverCommand", "()Z", (void*) android_net_wifi_stopDriverCommand }, 592 { "startFilteringMulticastV4Packets", "()Z", (void*) android_net_wifi_startMultiV4Filtering}, 593 { "stopFilteringMulticastV4Packets", "()Z", (void*) android_net_wifi_stopMultiV4Filtering}, 594 { "startFilteringMulticastV6Packets", "()Z", (void*) android_net_wifi_startMultiV6Filtering}, 595 { "stopFilteringMulticastV6Packets", "()Z", (void*) android_net_wifi_stopMultiV6Filtering}, 596 { "setPowerModeCommand", "(I)Z", (void*) android_net_wifi_setPowerModeCommand }, 597 { "getPowerModeCommand", "()I", (void*) android_net_wifi_getPowerModeCommand }, 598 { "setBandCommand", "(I)Z", (void*) android_net_wifi_setBandCommand}, 599 { "getBandCommand", "()I", (void*) android_net_wifi_getBandCommand}, 600 { "setBluetoothCoexistenceModeCommand", "(I)Z", 601 (void*) android_net_wifi_setBluetoothCoexistenceModeCommand }, 602 { "setBluetoothCoexistenceScanModeCommand", "(Z)Z", 603 (void*) android_net_wifi_setBluetoothCoexistenceScanModeCommand }, 604 { "getMacAddressCommand", "()Ljava/lang/String;", (void*) android_net_wifi_getMacAddressCommand }, 605 { "saveConfigCommand", "()Z", (void*) android_net_wifi_saveConfigCommand }, 606 { "reloadConfigCommand", "()Z", (void*) android_net_wifi_reloadConfigCommand }, 607 { "setScanResultHandlingCommand", "(I)Z", (void*) android_net_wifi_setScanResultHandlingCommand }, 608 { "addToBlacklistCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_addToBlacklistCommand }, 609 { "clearBlacklistCommand", "()Z", (void*) android_net_wifi_clearBlacklistCommand }, 610 { "startWpsPbcCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_wpsPbcCommand }, 611 { "startWpsWithPinFromAccessPointCommand", "(Ljava/lang/String;Ljava/lang/String;)Z", 612 (void*) android_net_wifi_wpsPinFromAccessPointCommand }, 613 { "startWpsWithPinFromDeviceCommand", "(Ljava/lang/String;)Ljava/lang/String;", 614 (void*) android_net_wifi_wpsPinFromDeviceCommand }, 615 { "setSuspendOptimizationsCommand", "(Z)Z", 616 (void*) android_net_wifi_setSuspendOptimizationsCommand}, 617 { "setCountryCodeCommand", "(Ljava/lang/String;)Z", 618 (void*) android_net_wifi_setCountryCodeCommand}, 619 { "enableBackgroundScanCommand", "(Z)V", (void*) android_net_wifi_enableBackgroundScanCommand}, 620 { "setScanIntervalCommand", "(I)V", (void*) android_net_wifi_setScanIntervalCommand}, 621 { "doBooleanCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_doBooleanCommand}, 622 { "doIntCommand", "(Ljava/lang/String;)I", (void*) android_net_wifi_doIntCommand}, 623 { "doStringCommand", "(Ljava/lang/String;)Ljava/lang/String;", (void*) android_net_wifi_doStringCommand}, 624 }; 625 626 int register_android_net_wifi_WifiManager(JNIEnv* env) 627 { 628 return AndroidRuntime::registerNativeMethods(env, 629 WIFI_PKG_NAME, gWifiMethods, NELEM(gWifiMethods)); 630 } 631 632 }; // namespace android 633