blob: 90c24b5807506fc359dba745c90050fe359c64fb [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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"
Elliott Hughesf17b9712011-04-12 16:12:09 -070020#include <ScopedUtfChars.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021#include <utils/misc.h>
22#include <android_runtime/AndroidRuntime.h>
23#include <utils/Log.h>
Zheng BaoZhong038e3152009-10-10 08:07:44 -040024#include <utils/String16.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025
26#include "wifi.h"
27
28#define WIFI_PKG_NAME "android/net/wifi/WifiNative"
Irfan Sherifff235c5a2010-10-21 16:44:48 -070029#define BUF_SIZE 256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
repo sync55bc5f32011-06-24 14:23:07 -070031//TODO: This file can be refactored to push a lot of the functionality to java
32//with just a few JNI calls - doBoolean/doInt/doString
33
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034namespace android {
35
Mike Lockwooda5ec95c2009-07-08 17:11:17 -040036static jboolean sScanModeActive = false;
Irfan Sheriff618455f2011-11-18 14:33:09 -080037static jint DBG = false;
Mike Lockwooda5ec95c2009-07-08 17:11:17 -040038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039static int doCommand(const char *cmd, char *replybuf, int replybuflen)
40{
41 size_t reply_len = replybuflen - 1;
42
43 if (::wifi_command(cmd, replybuf, &reply_len) != 0)
44 return -1;
45 else {
46 // Strip off trailing newline
47 if (reply_len > 0 && replybuf[reply_len-1] == '\n')
48 replybuf[reply_len-1] = '\0';
49 else
50 replybuf[reply_len] = '\0';
51 return 0;
52 }
53}
54
Elliott Hughesf17b9712011-04-12 16:12:09 -070055static jint doIntCommand(const char* fmt, ...)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056{
Elliott Hughesf17b9712011-04-12 16:12:09 -070057 char buf[BUF_SIZE];
58 va_list args;
59 va_start(args, fmt);
60 int byteCount = vsnprintf(buf, sizeof(buf), fmt, args);
61 va_end(args);
62 if (byteCount < 0 || byteCount >= BUF_SIZE) {
63 return -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 }
Elliott Hughesf17b9712011-04-12 16:12:09 -070065 char reply[BUF_SIZE];
66 if (doCommand(buf, reply, sizeof(reply)) != 0) {
67 return -1;
68 }
69 return static_cast<jint>(atoi(reply));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070}
71
Elliott Hughesf17b9712011-04-12 16:12:09 -070072static jboolean doBooleanCommand(const char* expect, const char* fmt, ...)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073{
Elliott Hughesf17b9712011-04-12 16:12:09 -070074 char buf[BUF_SIZE];
75 va_list args;
76 va_start(args, fmt);
77 int byteCount = vsnprintf(buf, sizeof(buf), fmt, args);
78 va_end(args);
79 if (byteCount < 0 || byteCount >= BUF_SIZE) {
80 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 }
Elliott Hughesf17b9712011-04-12 16:12:09 -070082 char reply[BUF_SIZE];
83 if (doCommand(buf, reply, sizeof(reply)) != 0) {
84 return JNI_FALSE;
85 }
86 return (strcmp(reply, expect) == 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087}
88
89// Send a command to the supplicant, and return the reply as a String
Elliott Hughesf17b9712011-04-12 16:12:09 -070090static jstring doStringCommand(JNIEnv* env, const char* fmt, ...) {
91 char buf[BUF_SIZE];
92 va_list args;
93 va_start(args, fmt);
94 int byteCount = vsnprintf(buf, sizeof(buf), fmt, args);
95 va_end(args);
96 if (byteCount < 0 || byteCount >= BUF_SIZE) {
97 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098 }
Elliott Hughesf17b9712011-04-12 16:12:09 -070099 char reply[4096];
100 if (doCommand(buf, reply, sizeof(reply)) != 0) {
101 return NULL;
102 }
103 // TODO: why not just NewStringUTF?
104 String16 str((char *)reply);
105 return env->NewString((const jchar *)str.string(), str.size());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106}
107
Elliott Hughesf17b9712011-04-12 16:12:09 -0700108static jboolean android_net_wifi_isDriverLoaded(JNIEnv* env, jobject)
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700109{
110 return (jboolean)(::is_wifi_driver_loaded() == 1);
111}
112
Elliott Hughesf17b9712011-04-12 16:12:09 -0700113static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114{
115 return (jboolean)(::wifi_load_driver() == 0);
116}
117
Elliott Hughesf17b9712011-04-12 16:12:09 -0700118static jboolean android_net_wifi_unloadDriver(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119{
120 return (jboolean)(::wifi_unload_driver() == 0);
121}
122
Elliott Hughesf17b9712011-04-12 16:12:09 -0700123static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124{
125 return (jboolean)(::wifi_start_supplicant() == 0);
126}
127
Irfan Sherifff42c39b2011-08-26 14:45:23 -0700128static jboolean android_net_wifi_startP2pSupplicant(JNIEnv* env, jobject)
129{
130 return (jboolean)(::wifi_start_p2p_supplicant() == 0);
131}
132
Elliott Hughesf17b9712011-04-12 16:12:09 -0700133static jboolean android_net_wifi_stopSupplicant(JNIEnv* env, jobject)
Irfan Sheriff5d001ea2010-12-15 10:29:49 -0800134{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700135 return doBooleanCommand("OK", "TERMINATE");
Irfan Sheriff5d001ea2010-12-15 10:29:49 -0800136}
137
Elliott Hughesf17b9712011-04-12 16:12:09 -0700138static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139{
140 return (jboolean)(::wifi_stop_supplicant() == 0);
141}
142
Elliott Hughesf17b9712011-04-12 16:12:09 -0700143static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144{
145 return (jboolean)(::wifi_connect_to_supplicant() == 0);
146}
147
Elliott Hughesf17b9712011-04-12 16:12:09 -0700148static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149{
150 ::wifi_close_supplicant_connection();
151}
152
Elliott Hughesf17b9712011-04-12 16:12:09 -0700153static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154{
Irfan Sherifff235c5a2010-10-21 16:44:48 -0700155 char buf[BUF_SIZE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156
157 int nread = ::wifi_wait_for_event(buf, sizeof buf);
158 if (nread > 0) {
159 return env->NewStringUTF(buf);
160 } else {
Elliott Hughesf17b9712011-04-12 16:12:09 -0700161 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 }
163}
164
Elliott Hughesf17b9712011-04-12 16:12:09 -0700165static jstring android_net_wifi_listNetworksCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166{
167 return doStringCommand(env, "LIST_NETWORKS");
168}
169
Elliott Hughesf17b9712011-04-12 16:12:09 -0700170static jint android_net_wifi_addNetworkCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171{
172 return doIntCommand("ADD_NETWORK");
173}
174
Elliott Hughesf17b9712011-04-12 16:12:09 -0700175static jboolean android_net_wifi_wpsPbcCommand(JNIEnv* env, jobject, jstring javaBssid)
Irfan Sheriff5ee89802010-09-16 17:53:34 -0700176{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700177 ScopedUtfChars bssid(env, javaBssid);
178 if (bssid.c_str() == NULL) {
179 return JNI_FALSE;
Irfan Sheriff5ee89802010-09-16 17:53:34 -0700180 }
Elliott Hughesf17b9712011-04-12 16:12:09 -0700181 return doBooleanCommand("OK", "WPS_PBC %s", bssid.c_str());
Irfan Sheriff5ee89802010-09-16 17:53:34 -0700182}
183
Elliott Hughesf17b9712011-04-12 16:12:09 -0700184static jboolean android_net_wifi_wpsPinFromAccessPointCommand(JNIEnv* env, jobject,
185 jstring javaBssid, jstring javaApPin)
Irfan Sheriff5ee89802010-09-16 17:53:34 -0700186{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700187 ScopedUtfChars bssid(env, javaBssid);
188 if (bssid.c_str() == NULL) {
189 return JNI_FALSE;
Irfan Sheriff5ee89802010-09-16 17:53:34 -0700190 }
Elliott Hughesf17b9712011-04-12 16:12:09 -0700191 ScopedUtfChars apPin(env, javaApPin);
192 if (apPin.c_str() == NULL) {
193 return JNI_FALSE;
194 }
195 return doBooleanCommand("OK", "WPS_REG %s %s", bssid.c_str(), apPin.c_str());
Irfan Sheriff5ee89802010-09-16 17:53:34 -0700196}
197
Elliott Hughesf17b9712011-04-12 16:12:09 -0700198static jstring android_net_wifi_wpsPinFromDeviceCommand(JNIEnv* env, jobject, jstring javaBssid)
Irfan Sherifff235c5a2010-10-21 16:44:48 -0700199{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700200 ScopedUtfChars bssid(env, javaBssid);
201 if (bssid.c_str() == NULL) {
Irfan Sheriff02fb46a2010-12-08 11:27:37 -0800202 return NULL;
Irfan Sherifff235c5a2010-10-21 16:44:48 -0700203 }
Elliott Hughesf17b9712011-04-12 16:12:09 -0700204 return doStringCommand(env, "WPS_PIN %s", bssid.c_str());
Irfan Sherifff235c5a2010-10-21 16:44:48 -0700205}
206
Elliott Hughesf17b9712011-04-12 16:12:09 -0700207static jboolean android_net_wifi_setCountryCodeCommand(JNIEnv* env, jobject, jstring javaCountry)
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700208{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700209 ScopedUtfChars country(env, javaCountry);
210 if (country.c_str() == NULL) {
211 return JNI_FALSE;
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700212 }
Elliott Hughesf17b9712011-04-12 16:12:09 -0700213 return doBooleanCommand("OK", "DRIVER COUNTRY %s", country.c_str());
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700214}
Irfan Sherifff235c5a2010-10-21 16:44:48 -0700215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216static jboolean android_net_wifi_setNetworkVariableCommand(JNIEnv* env,
Elliott Hughesf17b9712011-04-12 16:12:09 -0700217 jobject,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 jint netId,
Elliott Hughesf17b9712011-04-12 16:12:09 -0700219 jstring javaName,
220 jstring javaValue)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700222 ScopedUtfChars name(env, javaName);
223 if (name.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 return JNI_FALSE;
Elliott Hughesf17b9712011-04-12 16:12:09 -0700225 }
226 ScopedUtfChars value(env, javaValue);
227 if (value.c_str() == NULL) {
228 return JNI_FALSE;
229 }
230 return doBooleanCommand("OK", "SET_NETWORK %d %s %s", netId, name.c_str(), value.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231}
232
233static jstring android_net_wifi_getNetworkVariableCommand(JNIEnv* env,
Elliott Hughesf17b9712011-04-12 16:12:09 -0700234 jobject,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 jint netId,
Elliott Hughesf17b9712011-04-12 16:12:09 -0700236 jstring javaName)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700238 ScopedUtfChars name(env, javaName);
239 if (name.c_str() == NULL) {
240 return NULL;
241 }
242 return doStringCommand(env, "GET_NETWORK %d %s", netId, name.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243}
244
Elliott Hughesf17b9712011-04-12 16:12:09 -0700245static jboolean android_net_wifi_removeNetworkCommand(JNIEnv* env, jobject, jint netId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700247 return doBooleanCommand("OK", "REMOVE_NETWORK %d", netId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248}
249
250static jboolean android_net_wifi_enableNetworkCommand(JNIEnv* env,
Elliott Hughesf17b9712011-04-12 16:12:09 -0700251 jobject,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 jint netId,
253 jboolean disableOthers)
254{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700255 return doBooleanCommand("OK", "%s_NETWORK %d", disableOthers ? "SELECT" : "ENABLE", netId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256}
257
Elliott Hughesf17b9712011-04-12 16:12:09 -0700258static jboolean android_net_wifi_disableNetworkCommand(JNIEnv* env, jobject, jint netId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700260 return doBooleanCommand("OK", "DISABLE_NETWORK %d", netId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261}
262
Elliott Hughesf17b9712011-04-12 16:12:09 -0700263static jstring android_net_wifi_statusCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264{
265 return doStringCommand(env, "STATUS");
266}
267
Elliott Hughesf17b9712011-04-12 16:12:09 -0700268static jboolean android_net_wifi_pingCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700270 return doBooleanCommand("PONG", "PING");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271}
272
Elliott Hughesf17b9712011-04-12 16:12:09 -0700273static jstring android_net_wifi_scanResultsCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274{
275 return doStringCommand(env, "SCAN_RESULTS");
276}
277
Elliott Hughesf17b9712011-04-12 16:12:09 -0700278static jboolean android_net_wifi_disconnectCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700280 return doBooleanCommand("OK", "DISCONNECT");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281}
282
Elliott Hughesf17b9712011-04-12 16:12:09 -0700283static jboolean android_net_wifi_reconnectCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700285 return doBooleanCommand("OK", "RECONNECT");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286}
Elliott Hughesf17b9712011-04-12 16:12:09 -0700287static jboolean android_net_wifi_reassociateCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700289 return doBooleanCommand("OK", "REASSOCIATE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290}
291
Mike Lockwooda5ec95c2009-07-08 17:11:17 -0400292static jboolean doSetScanMode(jboolean setActive)
293{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700294 return doBooleanCommand("OK", (setActive ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE"));
Mike Lockwooda5ec95c2009-07-08 17:11:17 -0400295}
296
Elliott Hughesf17b9712011-04-12 16:12:09 -0700297static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject, jboolean forceActive)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298{
299 jboolean result;
Mike Lockwooda5ec95c2009-07-08 17:11:17 -0400300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 // Ignore any error from setting the scan mode.
302 // The scan will still work.
Mike Lockwooda5ec95c2009-07-08 17:11:17 -0400303 if (forceActive && !sScanModeActive)
304 doSetScanMode(true);
Elliott Hughesf17b9712011-04-12 16:12:09 -0700305 result = doBooleanCommand("OK", "SCAN");
Mike Lockwooda5ec95c2009-07-08 17:11:17 -0400306 if (forceActive && !sScanModeActive)
307 doSetScanMode(sScanModeActive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 return result;
309}
310
Elliott Hughesf17b9712011-04-12 16:12:09 -0700311static jboolean android_net_wifi_setScanModeCommand(JNIEnv* env, jobject, jboolean setActive)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312{
Mike Lockwooda5ec95c2009-07-08 17:11:17 -0400313 sScanModeActive = setActive;
314 return doSetScanMode(setActive);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315}
316
Elliott Hughesf17b9712011-04-12 16:12:09 -0700317static jboolean android_net_wifi_startDriverCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700319 return doBooleanCommand("OK", "DRIVER START");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320}
321
Elliott Hughesf17b9712011-04-12 16:12:09 -0700322static jboolean android_net_wifi_stopDriverCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700324 return doBooleanCommand("OK", "DRIVER STOP");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325}
326
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -0700327/*
328 Multicast filtering rules work as follows:
329
330 The driver can filter multicast (v4 and/or v6) and broadcast packets when in
331 a power optimized mode (typically when screen goes off).
332
333 In order to prevent the driver from filtering the multicast/broadcast packets, we have to
334 add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective
335
336 DRIVER RXFILTER-ADD Num
337 where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6
338
339 and DRIVER RXFILTER-START
340
341 In order to stop the usage of these rules, we do
342
343 DRIVER RXFILTER-STOP
344 DRIVER RXFILTER-REMOVE Num
345 where Num is as described for RXFILTER-ADD
346
347 The SETSUSPENDOPT driver command overrides the filtering rules
348*/
349
350static jboolean android_net_wifi_startMultiV4Filtering(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351{
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -0700352 return doBooleanCommand("OK", "DRIVER RXFILTER-STOP")
353 && doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 2")
Elliott Hughesf17b9712011-04-12 16:12:09 -0700354 && doBooleanCommand("OK", "DRIVER RXFILTER-START");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355}
356
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -0700357static jboolean android_net_wifi_stopMultiV4Filtering(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358{
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -0700359 return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 2")
360 && doBooleanCommand("OK", "DRIVER RXFILTER-START");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361}
362
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -0700363static jboolean android_net_wifi_startMultiV6Filtering(JNIEnv* env, jobject)
364{
365 return doBooleanCommand("OK", "DRIVER RXFILTER-STOP")
366 && doBooleanCommand("OK", "DRIVER RXFILTER-REMOVE 3")
367 && doBooleanCommand("OK", "DRIVER RXFILTER-START");
368}
369
370static jboolean android_net_wifi_stopMultiV6Filtering(JNIEnv* env, jobject)
371{
372 return doBooleanCommand("OK", "DRIVER RXFILTER-ADD 3")
373 && doBooleanCommand("OK", "DRIVER RXFILTER-START");
374}
375
376
Robert Greenwalt91f22f902009-06-08 18:15:21 -0700377static jint android_net_wifi_getRssiHelper(const char *cmd)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378{
Irfan Sherifff235c5a2010-10-21 16:44:48 -0700379 char reply[BUF_SIZE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380 int rssi = -200;
381
Robert Greenwalt91f22f902009-06-08 18:15:21 -0700382 if (doCommand(cmd, reply, sizeof(reply)) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 return (jint)-1;
384 }
Robert Greenwalt91f22f902009-06-08 18:15:21 -0700385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 // reply comes back in the form "<SSID> rssi XX" where XX is the
387 // number we're interested in. if we're associating, it returns "OK".
Mike Lockwoodc5ad0f42009-05-25 22:34:20 -0400388 // beware - <SSID> can contain spaces.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 if (strcmp(reply, "OK") != 0) {
Mike Lockwoodb20148b2009-08-04 11:32:52 -0400390 // beware of trailing spaces
391 char* end = reply + strlen(reply);
392 while (end > reply && end[-1] == ' ') {
393 end--;
394 }
395 *end = 0;
396
Mike Lockwoodc5ad0f42009-05-25 22:34:20 -0400397 char* lastSpace = strrchr(reply, ' ');
398 // lastSpace should be preceded by "rssi" and followed by the value
Stan Chesnutt320b56d2011-02-08 14:50:30 -0800399 if (lastSpace && !strncasecmp(lastSpace - 4, "rssi", 4)) {
Mike Lockwoodc5ad0f42009-05-25 22:34:20 -0400400 sscanf(lastSpace + 1, "%d", &rssi);
401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 }
403 return (jint)rssi;
404}
405
Elliott Hughesf17b9712011-04-12 16:12:09 -0700406static jstring android_net_wifi_getMacAddressCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407{
Irfan Sherifff235c5a2010-10-21 16:44:48 -0700408 char reply[BUF_SIZE];
409 char buf[BUF_SIZE];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410
411 if (doCommand("DRIVER MACADDR", reply, sizeof(reply)) != 0) {
Elliott Hughesf17b9712011-04-12 16:12:09 -0700412 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 }
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.
Elliott Hughesf17b9712011-04-12 16:12:09 -0700416 if (sscanf(reply, "%*s = %255s", buf) == 1) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 return env->NewStringUTF(buf);
Elliott Hughesf17b9712011-04-12 16:12:09 -0700418 }
419 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420}
421
Elliott Hughesf17b9712011-04-12 16:12:09 -0700422static jboolean android_net_wifi_setPowerModeCommand(JNIEnv* env, jobject, jint mode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700424 return doBooleanCommand("OK", "DRIVER POWERMODE %d", mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425}
426
Elliott Hughesf17b9712011-04-12 16:12:09 -0700427static jint android_net_wifi_getPowerModeCommand(JNIEnv* env, jobject)
Mikael Kanstrupea8bd1d2010-04-07 16:45:58 +0200428{
Irfan Sherifff235c5a2010-10-21 16:44:48 -0700429 char reply[BUF_SIZE];
Mikael Kanstrupea8bd1d2010-04-07 16:45:58 +0200430 int power;
431
432 if (doCommand("DRIVER GETPOWER", reply, sizeof(reply)) != 0) {
433 return (jint)-1;
434 }
435 // reply comes back in the form "powermode = XX" where XX is the
436 // number we're interested in.
Irfan Sheriff1a5b6092011-05-04 14:16:44 -0700437 if (sscanf(reply, "%*s = %u", &power) != 1) {
438 return (jint)-1;
439 }
Mikael Kanstrupea8bd1d2010-04-07 16:45:58 +0200440 return (jint)power;
441}
442
Elliott Hughesf17b9712011-04-12 16:12:09 -0700443static jboolean android_net_wifi_setBandCommand(JNIEnv* env, jobject, jint band)
Irfan Sheriff25c9bf22010-09-02 12:48:20 -0700444{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700445 return doBooleanCommand("OK", "DRIVER SETBAND %d", band);
Irfan Sheriff25c9bf22010-09-02 12:48:20 -0700446}
447
Elliott Hughesf17b9712011-04-12 16:12:09 -0700448static jint android_net_wifi_getBandCommand(JNIEnv* env, jobject)
Irfan Sheriff25c9bf22010-09-02 12:48:20 -0700449{
450 char reply[25];
451 int band;
452
453 if (doCommand("DRIVER GETBAND", reply, sizeof(reply)) != 0) {
454 return (jint)-1;
455 }
456 // reply comes back in the form "Band X" where X is the
457 // number we're interested in.
458 sscanf(reply, "%*s %u", &band);
459 return (jint)band;
460}
461
Elliott Hughesf17b9712011-04-12 16:12:09 -0700462static jboolean android_net_wifi_setBluetoothCoexistenceModeCommand(JNIEnv* env, jobject, jint mode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700464 return doBooleanCommand("OK", "DRIVER BTCOEXMODE %d", mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465}
466
Elliott Hughesf17b9712011-04-12 16:12:09 -0700467static jboolean android_net_wifi_setBluetoothCoexistenceScanModeCommand(JNIEnv* env, jobject, jboolean setCoexScanMode)
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700468{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700469 return doBooleanCommand("OK", "DRIVER BTCOEXSCAN-%s", setCoexScanMode ? "START" : "STOP");
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700470}
471
Elliott Hughesf17b9712011-04-12 16:12:09 -0700472static jboolean android_net_wifi_saveConfigCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473{
474 // Make sure we never write out a value for AP_SCAN other than 1
Elliott Hughesf17b9712011-04-12 16:12:09 -0700475 (void)doBooleanCommand("OK", "AP_SCAN 1");
476 return doBooleanCommand("OK", "SAVE_CONFIG");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477}
478
Elliott Hughesf17b9712011-04-12 16:12:09 -0700479static jboolean android_net_wifi_reloadConfigCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700481 return doBooleanCommand("OK", "RECONFIGURE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482}
483
Elliott Hughesf17b9712011-04-12 16:12:09 -0700484static jboolean android_net_wifi_setScanResultHandlingCommand(JNIEnv* env, jobject, jint mode)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700486 return doBooleanCommand("OK", "AP_SCAN %d", mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487}
488
Elliott Hughesf17b9712011-04-12 16:12:09 -0700489static jboolean android_net_wifi_addToBlacklistCommand(JNIEnv* env, jobject, jstring javaBssid)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700491 ScopedUtfChars bssid(env, javaBssid);
492 if (bssid.c_str() == NULL) {
493 return JNI_FALSE;
494 }
495 return doBooleanCommand("OK", "BLACKLIST %s", bssid.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496}
497
Elliott Hughesf17b9712011-04-12 16:12:09 -0700498static jboolean android_net_wifi_clearBlacklistCommand(JNIEnv* env, jobject)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700500 return doBooleanCommand("OK", "BLACKLIST clear");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501}
502
Elliott Hughesf17b9712011-04-12 16:12:09 -0700503static jboolean android_net_wifi_setSuspendOptimizationsCommand(JNIEnv* env, jobject, jboolean enabled)
Irfan Sheriff5876a422010-08-12 20:26:23 -0700504{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700505 return doBooleanCommand("OK", "DRIVER SETSUSPENDOPT %d", enabled ? 0 : 1);
Irfan Sheriff5876a422010-08-12 20:26:23 -0700506}
507
Elliott Hughesf17b9712011-04-12 16:12:09 -0700508static void android_net_wifi_enableBackgroundScanCommand(JNIEnv* env, jobject, jboolean enable)
Irfan Sherifffcc08452011-02-17 16:44:54 -0800509{
510 //Note: BGSCAN-START and BGSCAN-STOP are documented in core/res/res/values/config.xml
511 //and will need an update if the names are changed
512 if (enable) {
Elliott Hughesf17b9712011-04-12 16:12:09 -0700513 doBooleanCommand("OK", "DRIVER BGSCAN-START");
514 } else {
515 doBooleanCommand("OK", "DRIVER BGSCAN-STOP");
Irfan Sherifffcc08452011-02-17 16:44:54 -0800516 }
517}
518
Elliott Hughesf17b9712011-04-12 16:12:09 -0700519static void android_net_wifi_setScanIntervalCommand(JNIEnv* env, jobject, jint scanInterval)
Irfan Sheriff2b7f6382011-03-25 14:29:19 -0700520{
Elliott Hughesf17b9712011-04-12 16:12:09 -0700521 doBooleanCommand("OK", "SCAN_INTERVAL %d", scanInterval);
Irfan Sheriff2b7f6382011-03-25 14:29:19 -0700522}
523
524
repo sync55bc5f32011-06-24 14:23:07 -0700525static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring javaCommand)
526{
527 ScopedUtfChars command(env, javaCommand);
528 if (command.c_str() == NULL) {
529 return JNI_FALSE;
530 }
Irfan Sheriff618455f2011-11-18 14:33:09 -0800531 if (DBG) LOGD("doBoolean: %s", command.c_str());
repo sync55bc5f32011-06-24 14:23:07 -0700532 return doBooleanCommand("OK", "%s", command.c_str());
533}
534
535static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring javaCommand)
536{
537 ScopedUtfChars command(env, javaCommand);
538 if (command.c_str() == NULL) {
539 return -1;
540 }
Irfan Sheriff618455f2011-11-18 14:33:09 -0800541 if (DBG) LOGD("doInt: %s", command.c_str());
repo sync55bc5f32011-06-24 14:23:07 -0700542 return doIntCommand("%s", command.c_str());
543}
544
545static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring javaCommand)
546{
547 ScopedUtfChars command(env, javaCommand);
548 if (command.c_str() == NULL) {
549 return NULL;
550 }
Irfan Sheriff618455f2011-11-18 14:33:09 -0800551 if (DBG) LOGD("doString: %s", command.c_str());
repo sync55bc5f32011-06-24 14:23:07 -0700552 return doStringCommand(env, "%s", command.c_str());
553}
554
555
556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557// ----------------------------------------------------------------------------
558
559/*
560 * JNI registration.
561 */
562static JNINativeMethod gWifiMethods[] = {
563 /* name, signature, funcPtr */
564
565 { "loadDriver", "()Z", (void *)android_net_wifi_loadDriver },
Irfan Sheriffa2a1b912010-06-07 09:03:04 -0700566 { "isDriverLoaded", "()Z", (void *)android_net_wifi_isDriverLoaded},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 { "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver },
568 { "startSupplicant", "()Z", (void *)android_net_wifi_startSupplicant },
Irfan Sherifff42c39b2011-08-26 14:45:23 -0700569 { "startP2pSupplicant", "()Z", (void *)android_net_wifi_startP2pSupplicant },
Irfan Sheriff5d001ea2010-12-15 10:29:49 -0800570 { "stopSupplicant", "()Z", (void*) android_net_wifi_stopSupplicant },
Irfan Sheriff96071a72010-12-14 11:29:23 -0800571 { "killSupplicant", "()Z", (void *)android_net_wifi_killSupplicant },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 { "connectToSupplicant", "()Z", (void *)android_net_wifi_connectToSupplicant },
573 { "closeSupplicantConnection", "()V", (void *)android_net_wifi_closeSupplicantConnection },
574
575 { "listNetworksCommand", "()Ljava/lang/String;",
576 (void*) android_net_wifi_listNetworksCommand },
577 { "addNetworkCommand", "()I", (void*) android_net_wifi_addNetworkCommand },
578 { "setNetworkVariableCommand", "(ILjava/lang/String;Ljava/lang/String;)Z",
579 (void*) android_net_wifi_setNetworkVariableCommand },
580 { "getNetworkVariableCommand", "(ILjava/lang/String;)Ljava/lang/String;",
581 (void*) android_net_wifi_getNetworkVariableCommand },
582 { "removeNetworkCommand", "(I)Z", (void*) android_net_wifi_removeNetworkCommand },
583 { "enableNetworkCommand", "(IZ)Z", (void*) android_net_wifi_enableNetworkCommand },
584 { "disableNetworkCommand", "(I)Z", (void*) android_net_wifi_disableNetworkCommand },
585 { "waitForEvent", "()Ljava/lang/String;", (void*) android_net_wifi_waitForEvent },
586 { "statusCommand", "()Ljava/lang/String;", (void*) android_net_wifi_statusCommand },
587 { "scanResultsCommand", "()Ljava/lang/String;", (void*) android_net_wifi_scanResultsCommand },
588 { "pingCommand", "()Z", (void *)android_net_wifi_pingCommand },
589 { "disconnectCommand", "()Z", (void *)android_net_wifi_disconnectCommand },
590 { "reconnectCommand", "()Z", (void *)android_net_wifi_reconnectCommand },
591 { "reassociateCommand", "()Z", (void *)android_net_wifi_reassociateCommand },
Mike Lockwooda5ec95c2009-07-08 17:11:17 -0400592 { "scanCommand", "(Z)Z", (void*) android_net_wifi_scanCommand },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 { "setScanModeCommand", "(Z)Z", (void*) android_net_wifi_setScanModeCommand },
594 { "startDriverCommand", "()Z", (void*) android_net_wifi_startDriverCommand },
595 { "stopDriverCommand", "()Z", (void*) android_net_wifi_stopDriverCommand },
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -0700596 { "startFilteringMulticastV4Packets", "()Z", (void*) android_net_wifi_startMultiV4Filtering},
597 { "stopFilteringMulticastV4Packets", "()Z", (void*) android_net_wifi_stopMultiV4Filtering},
598 { "startFilteringMulticastV6Packets", "()Z", (void*) android_net_wifi_startMultiV6Filtering},
599 { "stopFilteringMulticastV6Packets", "()Z", (void*) android_net_wifi_stopMultiV6Filtering},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 { "setPowerModeCommand", "(I)Z", (void*) android_net_wifi_setPowerModeCommand },
Mikael Kanstrupea8bd1d2010-04-07 16:45:58 +0200601 { "getPowerModeCommand", "()I", (void*) android_net_wifi_getPowerModeCommand },
Irfan Sheriff25c9bf22010-09-02 12:48:20 -0700602 { "setBandCommand", "(I)Z", (void*) android_net_wifi_setBandCommand},
603 { "getBandCommand", "()I", (void*) android_net_wifi_getBandCommand},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 { "setBluetoothCoexistenceModeCommand", "(I)Z",
605 (void*) android_net_wifi_setBluetoothCoexistenceModeCommand },
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700606 { "setBluetoothCoexistenceScanModeCommand", "(Z)Z",
607 (void*) android_net_wifi_setBluetoothCoexistenceScanModeCommand },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 { "getMacAddressCommand", "()Ljava/lang/String;", (void*) android_net_wifi_getMacAddressCommand },
609 { "saveConfigCommand", "()Z", (void*) android_net_wifi_saveConfigCommand },
610 { "reloadConfigCommand", "()Z", (void*) android_net_wifi_reloadConfigCommand },
611 { "setScanResultHandlingCommand", "(I)Z", (void*) android_net_wifi_setScanResultHandlingCommand },
612 { "addToBlacklistCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_addToBlacklistCommand },
613 { "clearBlacklistCommand", "()Z", (void*) android_net_wifi_clearBlacklistCommand },
Irfan Sheriff5ee89802010-09-16 17:53:34 -0700614 { "startWpsPbcCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_wpsPbcCommand },
Irfan Sheriff02fb46a2010-12-08 11:27:37 -0800615 { "startWpsWithPinFromAccessPointCommand", "(Ljava/lang/String;Ljava/lang/String;)Z",
Irfan Sherifff235c5a2010-10-21 16:44:48 -0700616 (void*) android_net_wifi_wpsPinFromAccessPointCommand },
Irfan Sheriff02fb46a2010-12-08 11:27:37 -0800617 { "startWpsWithPinFromDeviceCommand", "(Ljava/lang/String;)Ljava/lang/String;",
Irfan Sherifff235c5a2010-10-21 16:44:48 -0700618 (void*) android_net_wifi_wpsPinFromDeviceCommand },
Irfan Sheriff5876a422010-08-12 20:26:23 -0700619 { "setSuspendOptimizationsCommand", "(Z)Z",
620 (void*) android_net_wifi_setSuspendOptimizationsCommand},
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700621 { "setCountryCodeCommand", "(Ljava/lang/String;)Z",
622 (void*) android_net_wifi_setCountryCodeCommand},
Irfan Sheriff2b7f6382011-03-25 14:29:19 -0700623 { "enableBackgroundScanCommand", "(Z)V", (void*) android_net_wifi_enableBackgroundScanCommand},
624 { "setScanIntervalCommand", "(I)V", (void*) android_net_wifi_setScanIntervalCommand},
repo sync55bc5f32011-06-24 14:23:07 -0700625 { "doBooleanCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_doBooleanCommand},
626 { "doIntCommand", "(Ljava/lang/String;)I", (void*) android_net_wifi_doIntCommand},
627 { "doStringCommand", "(Ljava/lang/String;)Ljava/lang/String;", (void*) android_net_wifi_doStringCommand},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628};
629
630int register_android_net_wifi_WifiManager(JNIEnv* env)
631{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 return AndroidRuntime::registerNativeMethods(env,
633 WIFI_PKG_NAME, gWifiMethods, NELEM(gWifiMethods));
634}
635
636}; // namespace android