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