WifiNative.java revision 651cdfcbac6245f570475991588ddc2d30265e8d
1/*
2 * Copyright (C) 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
17package android.net.wifi;
18
19import android.net.wifi.p2p.WifiP2pConfig;
20import android.net.wifi.p2p.WifiP2pGroup;
21import android.net.wifi.p2p.WifiP2pDevice;
22import android.util.Log;
23
24import java.io.InputStream;
25import java.lang.Process;
26import java.util.ArrayList;
27import java.util.List;
28
29/**
30 * Native calls for sending requests to the supplicant daemon, and for
31 * receiving asynchronous events. All methods of the form "xxxxCommand()"
32 * must be single-threaded, to avoid requests and responses initiated
33 * from multiple threads from being intermingled.
34 * <p/>
35 * Note that methods whose names are not of the form "xxxCommand()" do
36 * not talk to the supplicant daemon.
37 * Also, note that all WifiNative calls should happen in the
38 * WifiStateTracker class except for waitForEvent() call which is
39 * on a separate monitor channel for WifiMonitor
40 *
41 * TODO: clean up the API and move the functionality from JNI to here. We should
42 * be able to get everything done with doBooleanCommand, doIntCommand and
43 * doStringCommand native commands
44 *
45 * {@hide}
46 */
47public class WifiNative {
48
49    static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED = 0;
50    static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1;
51    static final int BLUETOOTH_COEXISTENCE_MODE_SENSE = 2;
52
53    public native static String getErrorString(int errorCode);
54
55    public native static boolean loadDriver();
56
57    public native static boolean isDriverLoaded();
58
59    public native static boolean unloadDriver();
60
61    public native static boolean startSupplicant();
62
63    public native static boolean startP2pSupplicant();
64
65    /* Does a graceful shutdown of supplicant. Is a common stop function for both p2p and sta.
66     *
67     * Note that underneath we use a harsh-sounding "terminate" supplicant command
68     * for a graceful stop and a mild-sounding "stop" interface
69     * to kill the process
70     */
71    public native static boolean stopSupplicant();
72
73    /* Sends a kill signal to supplicant. To be used when we have lost connection
74       or when the supplicant is hung */
75    public native static boolean killSupplicant();
76
77    public native static boolean connectToSupplicant();
78
79    public native static void closeSupplicantConnection();
80
81    public native static boolean pingCommand();
82
83    public native static boolean scanCommand(boolean forceActive);
84
85    public native static boolean setScanModeCommand(boolean setActive);
86
87    public native static String listNetworksCommand();
88
89    public native static int addNetworkCommand();
90
91    public native static boolean setNetworkVariableCommand(int netId, String name, String value);
92
93    public native static String getNetworkVariableCommand(int netId, String name);
94
95    public native static boolean removeNetworkCommand(int netId);
96
97    public native static boolean enableNetworkCommand(int netId, boolean disableOthers);
98
99    public native static boolean disableNetworkCommand(int netId);
100
101    public native static boolean reconnectCommand();
102
103    public native static boolean reassociateCommand();
104
105    public native static boolean disconnectCommand();
106
107    public native static String statusCommand();
108
109    public native static int getRssiCommand();
110
111    public native static int getRssiApproxCommand();
112
113    public native static int getLinkSpeedCommand();
114
115    public native static String getMacAddressCommand();
116
117    public native static String scanResultsCommand();
118
119    public native static boolean startDriverCommand();
120
121    public native static boolean stopDriverCommand();
122
123
124    /**
125     * Start filtering out Multicast V4 packets
126     * @return {@code true} if the operation succeeded, {@code false} otherwise
127     */
128    public native static boolean startFilteringMulticastV4Packets();
129
130    /**
131     * Stop filtering out Multicast V4 packets.
132     * @return {@code true} if the operation succeeded, {@code false} otherwise
133     */
134    public native static boolean stopFilteringMulticastV4Packets();
135
136    /**
137     * Start filtering out Multicast V6 packets
138     * @return {@code true} if the operation succeeded, {@code false} otherwise
139     */
140    public native static boolean startFilteringMulticastV6Packets();
141
142    /**
143     * Stop filtering out Multicast V6 packets.
144     * @return {@code true} if the operation succeeded, {@code false} otherwise
145     */
146    public native static boolean stopFilteringMulticastV6Packets();
147
148    public native static boolean setPowerModeCommand(int mode);
149
150    public native static int getBandCommand();
151
152    public native static boolean setBandCommand(int band);
153
154    public native static int getPowerModeCommand();
155
156    /**
157     * Sets the bluetooth coexistence mode.
158     *
159     * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED},
160     *            {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or
161     *            {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}.
162     * @return Whether the mode was successfully set.
163     */
164    public native static boolean setBluetoothCoexistenceModeCommand(int mode);
165
166    /**
167     * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
168     * some of the low-level scan parameters used by the driver are changed to
169     * reduce interference with A2DP streaming.
170     *
171     * @param isSet whether to enable or disable this mode
172     * @return {@code true} if the command succeeded, {@code false} otherwise.
173     */
174    public native static boolean setBluetoothCoexistenceScanModeCommand(boolean setCoexScanMode);
175
176    public native static boolean saveConfigCommand();
177
178    public native static boolean reloadConfigCommand();
179
180    public native static boolean setScanResultHandlingCommand(int mode);
181
182    public native static boolean addToBlacklistCommand(String bssid);
183
184    public native static boolean clearBlacklistCommand();
185
186    public native static boolean startWpsPbcCommand(String bssid);
187
188    public native static boolean startWpsWithPinFromAccessPointCommand(String bssid, String apPin);
189
190    public native static String startWpsWithPinFromDeviceCommand(String bssid);
191
192    public native static boolean setSuspendOptimizationsCommand(boolean enabled);
193
194    public native static boolean setCountryCodeCommand(String countryCode);
195
196    /**
197     * Wait for the supplicant to send an event, returning the event string.
198     * @return the event string sent by the supplicant.
199     */
200    public native static String waitForEvent();
201
202    public native static void enableBackgroundScanCommand(boolean enable);
203
204    public native static void setScanIntervalCommand(int scanInterval);
205
206    private native static boolean doBooleanCommand(String command);
207
208    private native static int doIntCommand(String command);
209
210    private native static String doStringCommand(String command);
211
212    public static boolean wpsPbc() {
213        return doBooleanCommand("WPS_PBC");
214    }
215
216    public static boolean wpsPin(String pin) {
217        return doBooleanCommand("WPS_PIN any " + pin);
218    }
219
220    public static boolean setPersistentReconnect(boolean enabled) {
221        int value = (enabled == true) ? 1 : 0;
222        return WifiNative.doBooleanCommand("SET persistent_reconnect " + value);
223    }
224
225    public static boolean setDeviceName(String name) {
226        return WifiNative.doBooleanCommand("SET device_name " + name);
227    }
228
229    public static boolean setDeviceType(String type) {
230        return WifiNative.doBooleanCommand("SET device_type " + type);
231    }
232
233    public static boolean p2pFind() {
234        return doBooleanCommand("P2P_FIND");
235    }
236
237    public static boolean p2pFind(int timeout) {
238        if (timeout <= 0) {
239            return p2pFind();
240        }
241        return doBooleanCommand("P2P_FIND " + timeout);
242    }
243
244    public static boolean p2pListen() {
245        return doBooleanCommand("P2P_LISTEN");
246    }
247
248    public static boolean p2pListen(int timeout) {
249        if (timeout <= 0) {
250            return p2pListen();
251        }
252        return doBooleanCommand("P2P_LISTEN " + timeout);
253    }
254
255    public static boolean p2pFlush() {
256        return doBooleanCommand("P2P_FLUSH");
257    }
258
259    /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad]
260        [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */
261    public static String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) {
262        if (config == null) return null;
263        List<String> args = new ArrayList<String>();
264        WpsInfo wps = config.wps;
265        args.add(config.deviceAddress);
266
267        switch (wps.setup) {
268            case WpsInfo.PBC:
269                args.add("pbc");
270                break;
271            case WpsInfo.DISPLAY:
272                //TODO: pass the pin back for display
273                args.add("pin");
274                args.add("display");
275                break;
276            case WpsInfo.KEYPAD:
277                args.add(wps.pin);
278                args.add("keypad");
279                break;
280            case WpsInfo.LABEL:
281                args.add(wps.pin);
282                args.add("label");
283            default:
284                break;
285        }
286
287        //TODO: Add persist behavior once the supplicant interaction is fixed for both
288        // group and client scenarios
289        /* Persist unless there is an explicit request to not do so*/
290        //if (config.persist != WifiP2pConfig.Persist.NO) args.add("persistent");
291
292        if (joinExistingGroup) args.add("join");
293
294        int groupOwnerIntent = config.groupOwnerIntent;
295        if (groupOwnerIntent < 0 || groupOwnerIntent > 15) {
296            groupOwnerIntent = 3; //default value
297        }
298        args.add("go_intent=" + groupOwnerIntent);
299
300        String command = "P2P_CONNECT ";
301        for (String s : args) command += s + " ";
302
303        return doStringCommand(command);
304    }
305
306    public static boolean p2pCancelConnect() {
307        return doBooleanCommand("P2P_CANCEL");
308    }
309
310    public static boolean p2pGroupAdd() {
311        return doBooleanCommand("P2P_GROUP_ADD");
312    }
313
314    public static boolean p2pGroupRemove(String iface) {
315        if (iface == null) return false;
316        return doBooleanCommand("P2P_GROUP_REMOVE " + iface);
317    }
318
319    public static boolean p2pReject(String deviceAddress) {
320        return doBooleanCommand("P2P_REJECT " + deviceAddress);
321    }
322
323    /* Invite a peer to a group */
324    public static boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
325        if (deviceAddress == null) return false;
326
327        if (group == null) {
328            return doBooleanCommand("P2P_INVITE peer=" + deviceAddress);
329        } else {
330            return doBooleanCommand("P2P_INVITE group=" + group.getInterface()
331                    + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress);
332        }
333    }
334
335    /* Reinvoke a persistent connection */
336    public static boolean p2pReinvoke(int netId, String deviceAddress) {
337        if (deviceAddress == null || netId < 0) return false;
338
339        return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress);
340    }
341
342
343    public static String p2pGetInterfaceAddress(String deviceAddress) {
344        if (deviceAddress == null) return null;
345
346        //  "p2p_peer deviceAddress" returns a multi-line result containing
347        //      intended_addr=fa:7b:7a:42:82:13
348        String peerInfo = p2pPeer(deviceAddress);
349        if (peerInfo == null) return null;
350        String[] tokens= peerInfo.split("\n");
351
352        for (String token : tokens) {
353            //TODO: update from interface_addr when wpa_supplicant implementation is fixed
354            if (token.startsWith("intended_addr=")) {
355                String[] nameValue = token.split("=");
356                if (nameValue.length != 2) break;
357                return nameValue[1];
358            }
359        }
360        return null;
361    }
362
363    public static String p2pGetDeviceAddress() {
364        String status = statusCommand();
365        if (status == null) return "";
366
367        String[] tokens = status.split("\n");
368        for (String token : tokens) {
369            if (token.startsWith("p2p_device_address=")) {
370                String[] nameValue = token.split("=");
371                if (nameValue.length != 2) break;
372                return nameValue[1];
373            }
374        }
375        return "";
376    }
377
378    public static String p2pPeer(String deviceAddress) {
379        return doStringCommand("P2P_PEER " + deviceAddress);
380    }
381}
382