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