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 <utils/misc.h> 21 #include <android_runtime/AndroidRuntime.h> 22 #include <utils/Log.h> 23 #include <utils/String16.h> 24 25 #include "wifi.h" 26 27 #define WIFI_PKG_NAME "android/net/wifi/WifiNative" 28 29 namespace android { 30 31 static jboolean sScanModeActive = false; 32 33 /* 34 * The following remembers the jfieldID's of the fields 35 * of the DhcpInfo Java object, so that we don't have 36 * to look them up every time. 37 */ 38 static struct fieldIds { 39 jclass dhcpInfoClass; 40 jmethodID constructorId; 41 jfieldID ipaddress; 42 jfieldID gateway; 43 jfieldID netmask; 44 jfieldID dns1; 45 jfieldID dns2; 46 jfieldID serverAddress; 47 jfieldID leaseDuration; 48 } dhcpInfoFieldIds; 49 50 static int doCommand(const char *cmd, char *replybuf, int replybuflen) 51 { 52 size_t reply_len = replybuflen - 1; 53 54 if (::wifi_command(cmd, replybuf, &reply_len) != 0) 55 return -1; 56 else { 57 // Strip off trailing newline 58 if (reply_len > 0 && replybuf[reply_len-1] == '\n') 59 replybuf[reply_len-1] = '\0'; 60 else 61 replybuf[reply_len] = '\0'; 62 return 0; 63 } 64 } 65 66 static jint doIntCommand(const char *cmd) 67 { 68 char reply[256]; 69 70 if (doCommand(cmd, reply, sizeof(reply)) != 0) { 71 return (jint)-1; 72 } else { 73 return (jint)atoi(reply); 74 } 75 } 76 77 static jboolean doBooleanCommand(const char *cmd, const char *expect) 78 { 79 char reply[256]; 80 81 if (doCommand(cmd, reply, sizeof(reply)) != 0) { 82 return (jboolean)JNI_FALSE; 83 } else { 84 return (jboolean)(strcmp(reply, expect) == 0); 85 } 86 } 87 88 // Send a command to the supplicant, and return the reply as a String 89 static jstring doStringCommand(JNIEnv *env, const char *cmd) 90 { 91 char reply[4096]; 92 93 if (doCommand(cmd, reply, sizeof(reply)) != 0) { 94 return env->NewStringUTF(NULL); 95 } else { 96 String16 str((char *)reply); 97 return env->NewString((const jchar *)str.string(), str.size()); 98 } 99 } 100 101 static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject clazz) 102 { 103 return (jboolean)(::wifi_load_driver() == 0); 104 } 105 106 static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject clazz) 107 { 108 return (jboolean)(::wifi_unload_driver() == 0); 109 } 110 111 static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject clazz) 112 { 113 return (jboolean)(::wifi_start_supplicant() == 0); 114 } 115 116 static jboolean android_net_wifi_stopSupplicant(JNIEnv* env, jobject clazz) 117 { 118 return (jboolean)(::wifi_stop_supplicant() == 0); 119 } 120 121 static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject clazz) 122 { 123 return (jboolean)(::wifi_connect_to_supplicant() == 0); 124 } 125 126 static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject clazz) 127 { 128 ::wifi_close_supplicant_connection(); 129 } 130 131 static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject clazz) 132 { 133 char buf[256]; 134 135 int nread = ::wifi_wait_for_event(buf, sizeof buf); 136 if (nread > 0) { 137 return env->NewStringUTF(buf); 138 } else { 139 return env->NewStringUTF(NULL); 140 } 141 } 142 143 static jstring android_net_wifi_listNetworksCommand(JNIEnv* env, jobject clazz) 144 { 145 return doStringCommand(env, "LIST_NETWORKS"); 146 } 147 148 static jint android_net_wifi_addNetworkCommand(JNIEnv* env, jobject clazz) 149 { 150 return doIntCommand("ADD_NETWORK"); 151 } 152 153 static jboolean android_net_wifi_setNetworkVariableCommand(JNIEnv* env, 154 jobject clazz, 155 jint netId, 156 jstring name, 157 jstring value) 158 { 159 char cmdstr[256]; 160 jboolean isCopy; 161 162 const char *nameStr = env->GetStringUTFChars(name, &isCopy); 163 const char *valueStr = env->GetStringUTFChars(value, &isCopy); 164 165 if (nameStr == NULL || valueStr == NULL) 166 return JNI_FALSE; 167 168 int cmdTooLong = snprintf(cmdstr, sizeof(cmdstr), "SET_NETWORK %d %s %s", 169 netId, nameStr, valueStr) >= (int)sizeof(cmdstr); 170 171 env->ReleaseStringUTFChars(name, nameStr); 172 env->ReleaseStringUTFChars(value, valueStr); 173 174 return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); 175 } 176 177 static jstring android_net_wifi_getNetworkVariableCommand(JNIEnv* env, 178 jobject clazz, 179 jint netId, 180 jstring name) 181 { 182 char cmdstr[256]; 183 jboolean isCopy; 184 185 const char *nameStr = env->GetStringUTFChars(name, &isCopy); 186 187 if (nameStr == NULL) 188 return env->NewStringUTF(NULL); 189 190 int cmdTooLong = snprintf(cmdstr, sizeof(cmdstr), "GET_NETWORK %d %s", 191 netId, nameStr) >= (int)sizeof(cmdstr); 192 193 env->ReleaseStringUTFChars(name, nameStr); 194 195 return cmdTooLong ? env->NewStringUTF(NULL) : doStringCommand(env, cmdstr); 196 } 197 198 static jboolean android_net_wifi_removeNetworkCommand(JNIEnv* env, jobject clazz, jint netId) 199 { 200 char cmdstr[256]; 201 202 int numWritten = snprintf(cmdstr, sizeof(cmdstr), "REMOVE_NETWORK %d", netId); 203 int cmdTooLong = numWritten >= (int)sizeof(cmdstr); 204 205 return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); 206 } 207 208 static jboolean android_net_wifi_enableNetworkCommand(JNIEnv* env, 209 jobject clazz, 210 jint netId, 211 jboolean disableOthers) 212 { 213 char cmdstr[256]; 214 const char *cmd = disableOthers ? "SELECT_NETWORK" : "ENABLE_NETWORK"; 215 216 int numWritten = snprintf(cmdstr, sizeof(cmdstr), "%s %d", cmd, netId); 217 int cmdTooLong = numWritten >= (int)sizeof(cmdstr); 218 219 return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); 220 } 221 222 static jboolean android_net_wifi_disableNetworkCommand(JNIEnv* env, jobject clazz, jint netId) 223 { 224 char cmdstr[256]; 225 226 int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DISABLE_NETWORK %d", netId); 227 int cmdTooLong = numWritten >= (int)sizeof(cmdstr); 228 229 return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); 230 } 231 232 static jstring android_net_wifi_statusCommand(JNIEnv* env, jobject clazz) 233 { 234 return doStringCommand(env, "STATUS"); 235 } 236 237 static jboolean android_net_wifi_pingCommand(JNIEnv* env, jobject clazz) 238 { 239 return doBooleanCommand("PING", "PONG"); 240 } 241 242 static jstring android_net_wifi_scanResultsCommand(JNIEnv* env, jobject clazz) 243 { 244 return doStringCommand(env, "SCAN_RESULTS"); 245 } 246 247 static jboolean android_net_wifi_disconnectCommand(JNIEnv* env, jobject clazz) 248 { 249 return doBooleanCommand("DISCONNECT", "OK"); 250 } 251 252 static jboolean android_net_wifi_reconnectCommand(JNIEnv* env, jobject clazz) 253 { 254 return doBooleanCommand("RECONNECT", "OK"); 255 } 256 static jboolean android_net_wifi_reassociateCommand(JNIEnv* env, jobject clazz) 257 { 258 return doBooleanCommand("REASSOCIATE", "OK"); 259 } 260 261 static jboolean doSetScanMode(jboolean setActive) 262 { 263 return doBooleanCommand((setActive ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE"), "OK"); 264 } 265 266 static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz, jboolean forceActive) 267 { 268 jboolean result; 269 270 // Ignore any error from setting the scan mode. 271 // The scan will still work. 272 if (forceActive && !sScanModeActive) 273 doSetScanMode(true); 274 result = doBooleanCommand("SCAN", "OK"); 275 if (forceActive && !sScanModeActive) 276 doSetScanMode(sScanModeActive); 277 return result; 278 } 279 280 static jboolean android_net_wifi_setScanModeCommand(JNIEnv* env, jobject clazz, jboolean setActive) 281 { 282 sScanModeActive = setActive; 283 return doSetScanMode(setActive); 284 } 285 286 static jboolean android_net_wifi_startDriverCommand(JNIEnv* env, jobject clazz) 287 { 288 return doBooleanCommand("DRIVER START", "OK"); 289 } 290 291 static jboolean android_net_wifi_stopDriverCommand(JNIEnv* env, jobject clazz) 292 { 293 return doBooleanCommand("DRIVER STOP", "OK"); 294 } 295 296 static jboolean android_net_wifi_startPacketFiltering(JNIEnv* env, jobject clazz) 297 { 298 return doBooleanCommand("DRIVER RXFILTER-ADD 0", "OK") 299 && doBooleanCommand("DRIVER RXFILTER-ADD 1", "OK") 300 && doBooleanCommand("DRIVER RXFILTER-ADD 3", "OK") 301 && doBooleanCommand("DRIVER RXFILTER-START", "OK"); 302 } 303 304 static jboolean android_net_wifi_stopPacketFiltering(JNIEnv* env, jobject clazz) 305 { 306 jboolean result = doBooleanCommand("DRIVER RXFILTER-STOP", "OK"); 307 if (result) { 308 (void)doBooleanCommand("DRIVER RXFILTER-REMOVE 3", "OK"); 309 (void)doBooleanCommand("DRIVER RXFILTER-REMOVE 1", "OK"); 310 (void)doBooleanCommand("DRIVER RXFILTER-REMOVE 0", "OK"); 311 } 312 313 return result; 314 } 315 316 static jint android_net_wifi_getRssiHelper(const char *cmd) 317 { 318 char reply[256]; 319 int rssi = -200; 320 321 if (doCommand(cmd, reply, sizeof(reply)) != 0) { 322 return (jint)-1; 323 } 324 325 // reply comes back in the form "<SSID> rssi XX" where XX is the 326 // number we're interested in. if we're associating, it returns "OK". 327 // beware - <SSID> can contain spaces. 328 if (strcmp(reply, "OK") != 0) { 329 // beware of trailing spaces 330 char* end = reply + strlen(reply); 331 while (end > reply && end[-1] == ' ') { 332 end--; 333 } 334 *end = 0; 335 336 char* lastSpace = strrchr(reply, ' '); 337 // lastSpace should be preceded by "rssi" and followed by the value 338 if (lastSpace && !strncmp(lastSpace - 4, "rssi", 4)) { 339 sscanf(lastSpace + 1, "%d", &rssi); 340 } 341 } 342 return (jint)rssi; 343 } 344 345 static jint android_net_wifi_getRssiCommand(JNIEnv* env, jobject clazz) 346 { 347 return android_net_wifi_getRssiHelper("DRIVER RSSI"); 348 } 349 350 static jint android_net_wifi_getRssiApproxCommand(JNIEnv* env, jobject clazz) 351 { 352 return android_net_wifi_getRssiHelper("DRIVER RSSI-APPROX"); 353 } 354 355 static jint android_net_wifi_getLinkSpeedCommand(JNIEnv* env, jobject clazz) 356 { 357 char reply[256]; 358 int linkspeed; 359 360 if (doCommand("DRIVER LINKSPEED", reply, sizeof(reply)) != 0) { 361 return (jint)-1; 362 } 363 // reply comes back in the form "LinkSpeed XX" where XX is the 364 // number we're interested in. 365 sscanf(reply, "%*s %u", &linkspeed); 366 return (jint)linkspeed; 367 } 368 369 static jstring android_net_wifi_getMacAddressCommand(JNIEnv* env, jobject clazz) 370 { 371 char reply[256]; 372 char buf[256]; 373 374 if (doCommand("DRIVER MACADDR", reply, sizeof(reply)) != 0) { 375 return env->NewStringUTF(NULL); 376 } 377 // reply comes back in the form "Macaddr = XX.XX.XX.XX.XX.XX" where XX 378 // is the part of the string we're interested in. 379 if (sscanf(reply, "%*s = %255s", buf) == 1) 380 return env->NewStringUTF(buf); 381 else 382 return env->NewStringUTF(NULL); 383 } 384 385 static jboolean android_net_wifi_setPowerModeCommand(JNIEnv* env, jobject clazz, jint mode) 386 { 387 char cmdstr[256]; 388 389 int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER POWERMODE %d", mode); 390 int cmdTooLong = numWritten >= (int)sizeof(cmdstr); 391 392 return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); 393 } 394 395 static jint android_net_wifi_getPowerModeCommand(JNIEnv* env, jobject clazz) 396 { 397 char reply[256]; 398 int power; 399 400 if (doCommand("DRIVER GETPOWER", reply, sizeof(reply)) != 0) { 401 return (jint)-1; 402 } 403 // reply comes back in the form "powermode = XX" where XX is the 404 // number we're interested in. 405 if (sscanf(reply, "%*s = %u", &power) != 1) { 406 return (jint)-1; 407 } 408 return (jint)power; 409 } 410 411 static jboolean android_net_wifi_setNumAllowedChannelsCommand(JNIEnv* env, jobject clazz, jint numChannels) 412 { 413 char cmdstr[256]; 414 415 int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER SCAN-CHANNELS %u", numChannels); 416 int cmdTooLong = numWritten >= (int)sizeof(cmdstr); 417 418 return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); 419 } 420 421 static jint android_net_wifi_getNumAllowedChannelsCommand(JNIEnv* env, jobject clazz) 422 { 423 char reply[256]; 424 int numChannels; 425 426 if (doCommand("DRIVER SCAN-CHANNELS", reply, sizeof(reply)) != 0) { 427 return -1; 428 } 429 // reply comes back in the form "Scan-Channels = X" where X is the 430 // number of channels 431 if (sscanf(reply, "%*s = %u", &numChannels) == 1) 432 return numChannels; 433 else 434 return -1; 435 } 436 437 static jboolean android_net_wifi_setBluetoothCoexistenceModeCommand(JNIEnv* env, jobject clazz, jint mode) 438 { 439 char cmdstr[256]; 440 441 int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER BTCOEXMODE %d", mode); 442 int cmdTooLong = numWritten >= (int)sizeof(cmdstr); 443 444 return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); 445 } 446 447 static jboolean android_net_wifi_setBluetoothCoexistenceScanModeCommand(JNIEnv* env, jobject clazz, jboolean setCoexScanMode) 448 { 449 char cmdstr[256]; 450 451 int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER BTCOEXSCAN-%s", setCoexScanMode ? "START" : "STOP"); 452 int cmdTooLong = numWritten >= (int)sizeof(cmdstr); 453 454 return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); 455 } 456 457 static jboolean android_net_wifi_saveConfigCommand(JNIEnv* env, jobject clazz) 458 { 459 // Make sure we never write out a value for AP_SCAN other than 1 460 (void)doBooleanCommand("AP_SCAN 1", "OK"); 461 return doBooleanCommand("SAVE_CONFIG", "OK"); 462 } 463 464 static jboolean android_net_wifi_reloadConfigCommand(JNIEnv* env, jobject clazz) 465 { 466 return doBooleanCommand("RECONFIGURE", "OK"); 467 } 468 469 static jboolean android_net_wifi_setScanResultHandlingCommand(JNIEnv* env, jobject clazz, jint mode) 470 { 471 char cmdstr[256]; 472 473 int numWritten = snprintf(cmdstr, sizeof(cmdstr), "AP_SCAN %d", mode); 474 int cmdTooLong = numWritten >= (int)sizeof(cmdstr); 475 476 return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); 477 } 478 479 static jboolean android_net_wifi_addToBlacklistCommand(JNIEnv* env, jobject clazz, jstring bssid) 480 { 481 char cmdstr[256]; 482 jboolean isCopy; 483 484 const char *bssidStr = env->GetStringUTFChars(bssid, &isCopy); 485 486 int cmdTooLong = snprintf(cmdstr, sizeof(cmdstr), "BLACKLIST %s", bssidStr) >= (int)sizeof(cmdstr); 487 488 env->ReleaseStringUTFChars(bssid, bssidStr); 489 490 return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); 491 } 492 493 static jboolean android_net_wifi_clearBlacklistCommand(JNIEnv* env, jobject clazz) 494 { 495 return doBooleanCommand("BLACKLIST clear", "OK"); 496 } 497 498 static jboolean android_net_wifi_setSuspendOptimizationsCommand(JNIEnv* env, jobject clazz, jboolean enabled) 499 { 500 char cmdstr[25]; 501 502 snprintf(cmdstr, sizeof(cmdstr), "DRIVER SETSUSPENDOPT %d", enabled ? 0 : 1); 503 return doBooleanCommand(cmdstr, "OK"); 504 } 505 506 507 static jboolean android_net_wifi_doDhcpRequest(JNIEnv* env, jobject clazz, jobject info) 508 { 509 jint ipaddr, gateway, mask, dns1, dns2, server, lease; 510 jboolean succeeded = ((jboolean)::do_dhcp_request(&ipaddr, &gateway, &mask, 511 &dns1, &dns2, &server, &lease) == 0); 512 if (succeeded && dhcpInfoFieldIds.dhcpInfoClass != NULL) { 513 env->SetIntField(info, dhcpInfoFieldIds.ipaddress, ipaddr); 514 env->SetIntField(info, dhcpInfoFieldIds.gateway, gateway); 515 env->SetIntField(info, dhcpInfoFieldIds.netmask, mask); 516 env->SetIntField(info, dhcpInfoFieldIds.dns1, dns1); 517 env->SetIntField(info, dhcpInfoFieldIds.dns2, dns2); 518 env->SetIntField(info, dhcpInfoFieldIds.serverAddress, server); 519 env->SetIntField(info, dhcpInfoFieldIds.leaseDuration, lease); 520 } 521 return succeeded; 522 } 523 524 static jstring android_net_wifi_getDhcpError(JNIEnv* env, jobject clazz) 525 { 526 return env->NewStringUTF(::get_dhcp_error_string()); 527 } 528 529 // ---------------------------------------------------------------------------- 530 531 /* 532 * JNI registration. 533 */ 534 static JNINativeMethod gWifiMethods[] = { 535 /* name, signature, funcPtr */ 536 537 { "loadDriver", "()Z", (void *)android_net_wifi_loadDriver }, 538 { "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver }, 539 { "startSupplicant", "()Z", (void *)android_net_wifi_startSupplicant }, 540 { "stopSupplicant", "()Z", (void *)android_net_wifi_stopSupplicant }, 541 { "connectToSupplicant", "()Z", (void *)android_net_wifi_connectToSupplicant }, 542 { "closeSupplicantConnection", "()V", (void *)android_net_wifi_closeSupplicantConnection }, 543 544 { "listNetworksCommand", "()Ljava/lang/String;", 545 (void*) android_net_wifi_listNetworksCommand }, 546 { "addNetworkCommand", "()I", (void*) android_net_wifi_addNetworkCommand }, 547 { "setNetworkVariableCommand", "(ILjava/lang/String;Ljava/lang/String;)Z", 548 (void*) android_net_wifi_setNetworkVariableCommand }, 549 { "getNetworkVariableCommand", "(ILjava/lang/String;)Ljava/lang/String;", 550 (void*) android_net_wifi_getNetworkVariableCommand }, 551 { "removeNetworkCommand", "(I)Z", (void*) android_net_wifi_removeNetworkCommand }, 552 { "enableNetworkCommand", "(IZ)Z", (void*) android_net_wifi_enableNetworkCommand }, 553 { "disableNetworkCommand", "(I)Z", (void*) android_net_wifi_disableNetworkCommand }, 554 { "waitForEvent", "()Ljava/lang/String;", (void*) android_net_wifi_waitForEvent }, 555 { "statusCommand", "()Ljava/lang/String;", (void*) android_net_wifi_statusCommand }, 556 { "scanResultsCommand", "()Ljava/lang/String;", (void*) android_net_wifi_scanResultsCommand }, 557 { "pingCommand", "()Z", (void *)android_net_wifi_pingCommand }, 558 { "disconnectCommand", "()Z", (void *)android_net_wifi_disconnectCommand }, 559 { "reconnectCommand", "()Z", (void *)android_net_wifi_reconnectCommand }, 560 { "reassociateCommand", "()Z", (void *)android_net_wifi_reassociateCommand }, 561 { "scanCommand", "(Z)Z", (void*) android_net_wifi_scanCommand }, 562 { "setScanModeCommand", "(Z)Z", (void*) android_net_wifi_setScanModeCommand }, 563 { "startDriverCommand", "()Z", (void*) android_net_wifi_startDriverCommand }, 564 { "stopDriverCommand", "()Z", (void*) android_net_wifi_stopDriverCommand }, 565 { "startPacketFiltering", "()Z", (void*) android_net_wifi_startPacketFiltering }, 566 { "stopPacketFiltering", "()Z", (void*) android_net_wifi_stopPacketFiltering }, 567 { "setPowerModeCommand", "(I)Z", (void*) android_net_wifi_setPowerModeCommand }, 568 { "getPowerModeCommand", "()I", (void*) android_net_wifi_getPowerModeCommand }, 569 { "setNumAllowedChannelsCommand", "(I)Z", (void*) android_net_wifi_setNumAllowedChannelsCommand }, 570 { "getNumAllowedChannelsCommand", "()I", (void*) android_net_wifi_getNumAllowedChannelsCommand }, 571 { "setBluetoothCoexistenceModeCommand", "(I)Z", 572 (void*) android_net_wifi_setBluetoothCoexistenceModeCommand }, 573 { "setBluetoothCoexistenceScanModeCommand", "(Z)Z", 574 (void*) android_net_wifi_setBluetoothCoexistenceScanModeCommand }, 575 { "getRssiCommand", "()I", (void*) android_net_wifi_getRssiCommand }, 576 { "getRssiApproxCommand", "()I", 577 (void*) android_net_wifi_getRssiApproxCommand}, 578 { "getLinkSpeedCommand", "()I", (void*) android_net_wifi_getLinkSpeedCommand }, 579 { "getMacAddressCommand", "()Ljava/lang/String;", (void*) android_net_wifi_getMacAddressCommand }, 580 { "saveConfigCommand", "()Z", (void*) android_net_wifi_saveConfigCommand }, 581 { "reloadConfigCommand", "()Z", (void*) android_net_wifi_reloadConfigCommand }, 582 { "setScanResultHandlingCommand", "(I)Z", (void*) android_net_wifi_setScanResultHandlingCommand }, 583 { "addToBlacklistCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_addToBlacklistCommand }, 584 { "clearBlacklistCommand", "()Z", (void*) android_net_wifi_clearBlacklistCommand }, 585 { "setSuspendOptimizationsCommand", "(Z)Z", (void*) android_net_wifi_setSuspendOptimizationsCommand}, 586 587 { "doDhcpRequest", "(Landroid/net/DhcpInfo;)Z", (void*) android_net_wifi_doDhcpRequest }, 588 { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_wifi_getDhcpError }, 589 }; 590 591 int register_android_net_wifi_WifiManager(JNIEnv* env) 592 { 593 jclass wifi = env->FindClass(WIFI_PKG_NAME); 594 LOG_FATAL_IF(wifi == NULL, "Unable to find class " WIFI_PKG_NAME); 595 596 dhcpInfoFieldIds.dhcpInfoClass = env->FindClass("android/net/DhcpInfo"); 597 if (dhcpInfoFieldIds.dhcpInfoClass != NULL) { 598 dhcpInfoFieldIds.constructorId = env->GetMethodID(dhcpInfoFieldIds.dhcpInfoClass, "<init>", "()V"); 599 dhcpInfoFieldIds.ipaddress = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "ipAddress", "I"); 600 dhcpInfoFieldIds.gateway = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "gateway", "I"); 601 dhcpInfoFieldIds.netmask = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "netmask", "I"); 602 dhcpInfoFieldIds.dns1 = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns1", "I"); 603 dhcpInfoFieldIds.dns2 = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns2", "I"); 604 dhcpInfoFieldIds.serverAddress = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "serverAddress", "I"); 605 dhcpInfoFieldIds.leaseDuration = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "leaseDuration", "I"); 606 } 607 608 return AndroidRuntime::registerNativeMethods(env, 609 WIFI_PKG_NAME, gWifiMethods, NELEM(gWifiMethods)); 610 } 611 612 }; // namespace android 613