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