android_net_wifi_Wifi.cpp revision 8c11e952305327183db9f7be719e4c94fde15a7c
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
29namespace android {
30
31static 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 */
38static 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
50static 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
66static 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
77static 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
89static 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
101static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject clazz)
102{
103    return (jboolean)(::wifi_load_driver() == 0);
104}
105
106static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject clazz)
107{
108    return (jboolean)(::wifi_unload_driver() == 0);
109}
110
111static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject clazz)
112{
113    return (jboolean)(::wifi_start_supplicant() == 0);
114}
115
116static jboolean android_net_wifi_stopSupplicant(JNIEnv* env, jobject clazz)
117{
118    return (jboolean)(::wifi_stop_supplicant() == 0);
119}
120
121static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject clazz)
122{
123    return (jboolean)(::wifi_connect_to_supplicant() == 0);
124}
125
126static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject clazz)
127{
128    ::wifi_close_supplicant_connection();
129}
130
131static 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
143static jstring android_net_wifi_listNetworksCommand(JNIEnv* env, jobject clazz)
144{
145    return doStringCommand(env, "LIST_NETWORKS");
146}
147
148static jint android_net_wifi_addNetworkCommand(JNIEnv* env, jobject clazz)
149{
150    return doIntCommand("ADD_NETWORK");
151}
152
153static 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
177static 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
198static 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
208static 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
222static 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
232static jstring android_net_wifi_statusCommand(JNIEnv* env, jobject clazz)
233{
234    return doStringCommand(env, "STATUS");
235}
236
237static jboolean android_net_wifi_pingCommand(JNIEnv* env, jobject clazz)
238{
239    return doBooleanCommand("PING", "PONG");
240}
241
242static jstring android_net_wifi_scanResultsCommand(JNIEnv* env, jobject clazz)
243{
244    return doStringCommand(env, "SCAN_RESULTS");
245}
246
247static jboolean android_net_wifi_disconnectCommand(JNIEnv* env, jobject clazz)
248{
249    return doBooleanCommand("DISCONNECT", "OK");
250}
251
252static jboolean android_net_wifi_reconnectCommand(JNIEnv* env, jobject clazz)
253{
254    return doBooleanCommand("RECONNECT", "OK");
255}
256static jboolean android_net_wifi_reassociateCommand(JNIEnv* env, jobject clazz)
257{
258    return doBooleanCommand("REASSOCIATE", "OK");
259}
260
261static jboolean doSetScanMode(jboolean setActive)
262{
263    return doBooleanCommand((setActive ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE"), "OK");
264}
265
266static 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
280static jboolean android_net_wifi_setScanModeCommand(JNIEnv* env, jobject clazz, jboolean setActive)
281{
282    sScanModeActive = setActive;
283    return doSetScanMode(setActive);
284}
285
286static jboolean android_net_wifi_startDriverCommand(JNIEnv* env, jobject clazz)
287{
288    return doBooleanCommand("DRIVER START", "OK");
289}
290
291static jboolean android_net_wifi_stopDriverCommand(JNIEnv* env, jobject clazz)
292{
293    return doBooleanCommand("DRIVER STOP", "OK");
294}
295
296static 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
304static 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
316static 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
345static jint android_net_wifi_getRssiCommand(JNIEnv* env, jobject clazz)
346{
347    return android_net_wifi_getRssiHelper("DRIVER RSSI");
348}
349
350static jint android_net_wifi_getRssiApproxCommand(JNIEnv* env, jobject clazz)
351{
352    return android_net_wifi_getRssiHelper("DRIVER RSSI-APPROX");
353}
354
355static 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
369static 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
385static 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
395static 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    sscanf(reply, "%*s = %u", &power);
406    return (jint)power;
407}
408
409static jboolean android_net_wifi_setNumAllowedChannelsCommand(JNIEnv* env, jobject clazz, jint numChannels)
410{
411    char cmdstr[256];
412
413    int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER SCAN-CHANNELS %u", numChannels);
414    int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
415
416    return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK");
417}
418
419static jint android_net_wifi_getNumAllowedChannelsCommand(JNIEnv* env, jobject clazz)
420{
421    char reply[256];
422    int numChannels;
423
424    if (doCommand("DRIVER SCAN-CHANNELS", reply, sizeof(reply)) != 0) {
425        return -1;
426    }
427    // reply comes back in the form "Scan-Channels = X" where X is the
428    // number of channels
429    if (sscanf(reply, "%*s = %u", &numChannels) == 1)
430        return numChannels;
431    else
432        return -1;
433}
434
435static jboolean android_net_wifi_setBluetoothCoexistenceModeCommand(JNIEnv* env, jobject clazz, jint mode)
436{
437    char cmdstr[256];
438
439    int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER BTCOEXMODE %d", mode);
440    int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
441
442    return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK");
443}
444
445static jboolean android_net_wifi_setBluetoothCoexistenceScanModeCommand(JNIEnv* env, jobject clazz, jboolean setCoexScanMode)
446{
447    char cmdstr[256];
448
449    int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER BTCOEXSCAN-%s", setCoexScanMode ? "START" : "STOP");
450    int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
451
452    return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK");
453}
454
455static jboolean android_net_wifi_saveConfigCommand(JNIEnv* env, jobject clazz)
456{
457    // Make sure we never write out a value for AP_SCAN other than 1
458    (void)doBooleanCommand("AP_SCAN 1", "OK");
459    return doBooleanCommand("SAVE_CONFIG", "OK");
460}
461
462static jboolean android_net_wifi_reloadConfigCommand(JNIEnv* env, jobject clazz)
463{
464    return doBooleanCommand("RECONFIGURE", "OK");
465}
466
467static jboolean android_net_wifi_setScanResultHandlingCommand(JNIEnv* env, jobject clazz, jint mode)
468{
469    char cmdstr[256];
470
471    int numWritten = snprintf(cmdstr, sizeof(cmdstr), "AP_SCAN %d", mode);
472    int cmdTooLong = numWritten >= (int)sizeof(cmdstr);
473
474    return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK");
475}
476
477static jboolean android_net_wifi_addToBlacklistCommand(JNIEnv* env, jobject clazz, jstring bssid)
478{
479    char cmdstr[256];
480    jboolean isCopy;
481
482    const char *bssidStr = env->GetStringUTFChars(bssid, &isCopy);
483
484    int cmdTooLong = snprintf(cmdstr, sizeof(cmdstr), "BLACKLIST %s", bssidStr) >= (int)sizeof(cmdstr);
485
486    env->ReleaseStringUTFChars(bssid, bssidStr);
487
488    return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK");
489}
490
491static jboolean android_net_wifi_clearBlacklistCommand(JNIEnv* env, jobject clazz)
492{
493    return doBooleanCommand("BLACKLIST clear", "OK");
494}
495
496static jboolean android_net_wifi_setSuspendOptimizationsCommand(JNIEnv* env, jobject clazz, jboolean enabled)
497{
498    char cmdstr[25];
499
500    snprintf(cmdstr, sizeof(cmdstr), "DRIVER SETSUSPEND %d", enabled ? 0 : 1);
501    return doBooleanCommand(cmdstr, "OK");
502}
503
504
505static jboolean android_net_wifi_doDhcpRequest(JNIEnv* env, jobject clazz, jobject info)
506{
507    jint ipaddr, gateway, mask, dns1, dns2, server, lease;
508    jboolean succeeded = ((jboolean)::do_dhcp_request(&ipaddr, &gateway, &mask,
509                                        &dns1, &dns2, &server, &lease) == 0);
510    if (succeeded && dhcpInfoFieldIds.dhcpInfoClass != NULL) {
511        env->SetIntField(info, dhcpInfoFieldIds.ipaddress, ipaddr);
512        env->SetIntField(info, dhcpInfoFieldIds.gateway, gateway);
513        env->SetIntField(info, dhcpInfoFieldIds.netmask, mask);
514        env->SetIntField(info, dhcpInfoFieldIds.dns1, dns1);
515        env->SetIntField(info, dhcpInfoFieldIds.dns2, dns2);
516        env->SetIntField(info, dhcpInfoFieldIds.serverAddress, server);
517        env->SetIntField(info, dhcpInfoFieldIds.leaseDuration, lease);
518    }
519    return succeeded;
520}
521
522static jstring android_net_wifi_getDhcpError(JNIEnv* env, jobject clazz)
523{
524    return env->NewStringUTF(::get_dhcp_error_string());
525}
526
527// ----------------------------------------------------------------------------
528
529/*
530 * JNI registration.
531 */
532static JNINativeMethod gWifiMethods[] = {
533    /* name, signature, funcPtr */
534
535    { "loadDriver", "()Z",  (void *)android_net_wifi_loadDriver },
536    { "unloadDriver", "()Z",  (void *)android_net_wifi_unloadDriver },
537    { "startSupplicant", "()Z",  (void *)android_net_wifi_startSupplicant },
538    { "stopSupplicant", "()Z",  (void *)android_net_wifi_stopSupplicant },
539    { "connectToSupplicant", "()Z",  (void *)android_net_wifi_connectToSupplicant },
540    { "closeSupplicantConnection", "()V",  (void *)android_net_wifi_closeSupplicantConnection },
541
542    { "listNetworksCommand", "()Ljava/lang/String;",
543        (void*) android_net_wifi_listNetworksCommand },
544    { "addNetworkCommand", "()I", (void*) android_net_wifi_addNetworkCommand },
545    { "setNetworkVariableCommand", "(ILjava/lang/String;Ljava/lang/String;)Z",
546        (void*) android_net_wifi_setNetworkVariableCommand },
547    { "getNetworkVariableCommand", "(ILjava/lang/String;)Ljava/lang/String;",
548        (void*) android_net_wifi_getNetworkVariableCommand },
549    { "removeNetworkCommand", "(I)Z", (void*) android_net_wifi_removeNetworkCommand },
550    { "enableNetworkCommand", "(IZ)Z", (void*) android_net_wifi_enableNetworkCommand },
551    { "disableNetworkCommand", "(I)Z", (void*) android_net_wifi_disableNetworkCommand },
552    { "waitForEvent", "()Ljava/lang/String;", (void*) android_net_wifi_waitForEvent },
553    { "statusCommand", "()Ljava/lang/String;", (void*) android_net_wifi_statusCommand },
554    { "scanResultsCommand", "()Ljava/lang/String;", (void*) android_net_wifi_scanResultsCommand },
555    { "pingCommand", "()Z",  (void *)android_net_wifi_pingCommand },
556    { "disconnectCommand", "()Z",  (void *)android_net_wifi_disconnectCommand },
557    { "reconnectCommand", "()Z",  (void *)android_net_wifi_reconnectCommand },
558    { "reassociateCommand", "()Z",  (void *)android_net_wifi_reassociateCommand },
559    { "scanCommand", "(Z)Z", (void*) android_net_wifi_scanCommand },
560    { "setScanModeCommand", "(Z)Z", (void*) android_net_wifi_setScanModeCommand },
561    { "startDriverCommand", "()Z", (void*) android_net_wifi_startDriverCommand },
562    { "stopDriverCommand", "()Z", (void*) android_net_wifi_stopDriverCommand },
563    { "startPacketFiltering", "()Z", (void*) android_net_wifi_startPacketFiltering },
564    { "stopPacketFiltering", "()Z", (void*) android_net_wifi_stopPacketFiltering },
565    { "setPowerModeCommand", "(I)Z", (void*) android_net_wifi_setPowerModeCommand },
566    { "getPowerModeCommand", "()I", (void*) android_net_wifi_getPowerModeCommand },
567    { "setNumAllowedChannelsCommand", "(I)Z", (void*) android_net_wifi_setNumAllowedChannelsCommand },
568    { "getNumAllowedChannelsCommand", "()I", (void*) android_net_wifi_getNumAllowedChannelsCommand },
569    { "setBluetoothCoexistenceModeCommand", "(I)Z",
570    		(void*) android_net_wifi_setBluetoothCoexistenceModeCommand },
571    { "setBluetoothCoexistenceScanModeCommand", "(Z)Z",
572    		(void*) android_net_wifi_setBluetoothCoexistenceScanModeCommand },
573    { "getRssiCommand", "()I", (void*) android_net_wifi_getRssiCommand },
574    { "getRssiApproxCommand", "()I",
575            (void*) android_net_wifi_getRssiApproxCommand},
576    { "getLinkSpeedCommand", "()I", (void*) android_net_wifi_getLinkSpeedCommand },
577    { "getMacAddressCommand", "()Ljava/lang/String;", (void*) android_net_wifi_getMacAddressCommand },
578    { "saveConfigCommand", "()Z", (void*) android_net_wifi_saveConfigCommand },
579    { "reloadConfigCommand", "()Z", (void*) android_net_wifi_reloadConfigCommand },
580    { "setScanResultHandlingCommand", "(I)Z", (void*) android_net_wifi_setScanResultHandlingCommand },
581    { "addToBlacklistCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_addToBlacklistCommand },
582    { "clearBlacklistCommand", "()Z", (void*) android_net_wifi_clearBlacklistCommand },
583    { "setSuspendOptimizationsCommand", "(Z)Z", (void*) android_net_wifi_setSuspendOptimizationsCommand},
584
585    { "doDhcpRequest", "(Landroid/net/DhcpInfo;)Z", (void*) android_net_wifi_doDhcpRequest },
586    { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_wifi_getDhcpError },
587};
588
589int register_android_net_wifi_WifiManager(JNIEnv* env)
590{
591    jclass wifi = env->FindClass(WIFI_PKG_NAME);
592    LOG_FATAL_IF(wifi == NULL, "Unable to find class " WIFI_PKG_NAME);
593
594    dhcpInfoFieldIds.dhcpInfoClass = env->FindClass("android/net/DhcpInfo");
595    if (dhcpInfoFieldIds.dhcpInfoClass != NULL) {
596        dhcpInfoFieldIds.constructorId = env->GetMethodID(dhcpInfoFieldIds.dhcpInfoClass, "<init>", "()V");
597        dhcpInfoFieldIds.ipaddress = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "ipAddress", "I");
598        dhcpInfoFieldIds.gateway = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "gateway", "I");
599        dhcpInfoFieldIds.netmask = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "netmask", "I");
600        dhcpInfoFieldIds.dns1 = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns1", "I");
601        dhcpInfoFieldIds.dns2 = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns2", "I");
602        dhcpInfoFieldIds.serverAddress = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "serverAddress", "I");
603        dhcpInfoFieldIds.leaseDuration = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "leaseDuration", "I");
604    }
605
606    return AndroidRuntime::registerNativeMethods(env,
607            WIFI_PKG_NAME, gWifiMethods, NELEM(gWifiMethods));
608}
609
610}; // namespace android
611