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