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 
17 package com.android.server.wifi;
18 
19 import android.net.wifi.BatchedScanSettings;
20 import android.net.wifi.RttManager;
21 import android.net.wifi.ScanResult;
22 import android.net.wifi.WifiConfiguration;
23 import android.net.wifi.WifiLinkLayerStats;
24 import android.net.wifi.WifiManager;
25 import android.net.wifi.WifiScanner;
26 import android.net.wifi.RttManager;
27 import android.net.wifi.WifiSsid;
28 import android.net.wifi.WpsInfo;
29 import android.net.wifi.p2p.WifiP2pConfig;
30 import android.net.wifi.p2p.WifiP2pGroup;
31 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
32 import android.net.wifi.WifiEnterpriseConfig;
33 import android.os.SystemClock;
34 import android.text.TextUtils;
35 import android.util.Base64;
36 import android.util.LocalLog;
37 import android.util.Log;
38 
39 import java.io.ByteArrayOutputStream;
40 import java.io.IOException;
41 import java.nio.ByteBuffer;
42 import java.nio.CharBuffer;
43 import java.nio.charset.CharacterCodingException;
44 import java.nio.charset.CharsetDecoder;
45 import java.nio.charset.StandardCharsets;
46 import java.util.ArrayList;
47 import java.util.List;
48 import java.util.Locale;
49 import java.util.zip.Deflater;
50 import libcore.util.HexEncoding;
51 /**
52  * Native calls for bring up/shut down of the supplicant daemon and for
53  * sending requests to the supplicant daemon
54  *
55  * waitForEvent() is called on the monitor thread for events. All other methods
56  * must be serialized from the framework.
57  *
58  * {@hide}
59  */
60 public class WifiNative {
61 
62     private static boolean DBG = false;
63     private final String mTAG;
64     private static final int DEFAULT_GROUP_OWNER_INTENT     = 6;
65 
66     static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED     = 0;
67     static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED    = 1;
68     static final int BLUETOOTH_COEXISTENCE_MODE_SENSE       = 2;
69 
70     static final int SCAN_WITHOUT_CONNECTION_SETUP          = 1;
71     static final int SCAN_WITH_CONNECTION_SETUP             = 2;
72 
73     // Hold this lock before calling supplicant - it is required to
74     // mutually exclude access from Wifi and P2p state machines
75     static final Object mLock = new Object();
76 
77     public final String mInterfaceName;
78     public final String mInterfacePrefix;
79 
80     private boolean mSuspendOptEnabled = false;
81 
82     private static final int EID_HT_OPERATION = 61;
83     private static final int EID_VHT_OPERATION = 192;
84     private static final int EID_EXTENDED_CAPS = 127;
85     private static final int RTT_RESP_ENABLE_BIT = 70;
86     /* Register native functions */
87 
88     static {
89         /* Native functions are defined in libwifi-service.so */
90         System.loadLibrary("wifi-service");
registerNatives()91         registerNatives();
92     }
93 
registerNatives()94     private static native int registerNatives();
95 
loadDriver()96     public native static boolean loadDriver();
97 
isDriverLoaded()98     public native static boolean isDriverLoaded();
99 
unloadDriver()100     public native static boolean unloadDriver();
101 
startSupplicant(boolean p2pSupported)102     public native static boolean startSupplicant(boolean p2pSupported);
103 
104     /* Sends a kill signal to supplicant. To be used when we have lost connection
105        or when the supplicant is hung */
killSupplicant(boolean p2pSupported)106     public native static boolean killSupplicant(boolean p2pSupported);
107 
connectToSupplicantNative()108     private native boolean connectToSupplicantNative();
109 
closeSupplicantConnectionNative()110     private native void closeSupplicantConnectionNative();
111 
112     /**
113      * Wait for the supplicant to send an event, returning the event string.
114      * @return the event string sent by the supplicant.
115      */
waitForEventNative()116     private native String waitForEventNative();
117 
doBooleanCommandNative(String command)118     private native boolean doBooleanCommandNative(String command);
119 
doIntCommandNative(String command)120     private native int doIntCommandNative(String command);
121 
doStringCommandNative(String command)122     private native String doStringCommandNative(String command);
123 
WifiNative(String interfaceName)124     public WifiNative(String interfaceName) {
125         mInterfaceName = interfaceName;
126         mTAG = "WifiNative-" + interfaceName;
127         if (!interfaceName.equals("p2p0")) {
128             mInterfacePrefix = "IFNAME=" + interfaceName + " ";
129         } else {
130             // commands for p2p0 interface don't need prefix
131             mInterfacePrefix = "";
132         }
133     }
134 
enableVerboseLogging(int verbose)135     void enableVerboseLogging(int verbose) {
136         if (verbose > 0) {
137             DBG = true;
138         } else {
139             DBG = false;
140         }
141     }
142 
143     private static final LocalLog mLocalLog = new LocalLog(16384);
144 
145     // hold mLock before accessing mCmdIdLock
146     private static int sCmdId;
147 
getLocalLog()148     public static LocalLog getLocalLog() {
149         return mLocalLog;
150     }
151 
getNewCmdIdLocked()152     private static int getNewCmdIdLocked() {
153         return sCmdId++;
154     }
155 
localLog(String s)156     private void localLog(String s) {
157         if (mLocalLog != null)
158             mLocalLog.log(mInterfaceName + ": " + s);
159     }
160 
connectToSupplicant()161     public boolean connectToSupplicant() {
162         synchronized(mLock) {
163             localLog(mInterfacePrefix + "connectToSupplicant");
164             return connectToSupplicantNative();
165         }
166     }
167 
closeSupplicantConnection()168     public void closeSupplicantConnection() {
169         synchronized(mLock) {
170             localLog(mInterfacePrefix + "closeSupplicantConnection");
171             closeSupplicantConnectionNative();
172         }
173     }
174 
waitForEvent()175     public String waitForEvent() {
176         // No synchronization necessary .. it is implemented in WifiMonitor
177         return waitForEventNative();
178     }
179 
doBooleanCommand(String command)180     private boolean doBooleanCommand(String command) {
181         if (DBG) Log.d(mTAG, "doBoolean: " + command);
182         synchronized (mLock) {
183             int cmdId = getNewCmdIdLocked();
184             String toLog = Integer.toString(cmdId) + ":" + mInterfacePrefix + command;
185             boolean result = doBooleanCommandNative(mInterfacePrefix + command);
186             localLog(toLog + " -> " + result);
187             if (DBG) Log.d(mTAG, command + ": returned " + result);
188             return result;
189         }
190     }
191 
doBooleanCommandWithoutLogging(String command)192     private boolean doBooleanCommandWithoutLogging(String command) {
193         if (DBG) Log.d(mTAG, "doBooleanCommandWithoutLogging: " + command);
194         synchronized (mLock) {
195             int cmdId = getNewCmdIdLocked();
196             boolean result = doBooleanCommandNative(mInterfacePrefix + command);
197             if (DBG) Log.d(mTAG, command + ": returned " + result);
198             return result;
199         }
200     }
201 
doIntCommand(String command)202     private int doIntCommand(String command) {
203         if (DBG) Log.d(mTAG, "doInt: " + command);
204         synchronized (mLock) {
205             int cmdId = getNewCmdIdLocked();
206             String toLog = Integer.toString(cmdId) + ":" + mInterfacePrefix + command;
207             int result = doIntCommandNative(mInterfacePrefix + command);
208             localLog(toLog + " -> " + result);
209             if (DBG) Log.d(mTAG, "   returned " + result);
210             return result;
211         }
212     }
213 
doStringCommand(String command)214     private String doStringCommand(String command) {
215         if (DBG) {
216             //GET_NETWORK commands flood the logs
217             if (!command.startsWith("GET_NETWORK")) {
218                 Log.d(mTAG, "doString: [" + command + "]");
219             }
220         }
221         synchronized (mLock) {
222             int cmdId = getNewCmdIdLocked();
223             String toLog = Integer.toString(cmdId) + ":" + mInterfacePrefix + command;
224             String result = doStringCommandNative(mInterfacePrefix + command);
225             if (result == null) {
226                 if (DBG) Log.d(mTAG, "doStringCommandNative no result");
227             } else {
228                 if (!command.startsWith("STATUS-")) {
229                     localLog(toLog + " -> " + result);
230                 }
231                 if (DBG) Log.d(mTAG, "   returned " + result.replace("\n", " "));
232             }
233             return result;
234         }
235     }
236 
doStringCommandWithoutLogging(String command)237     private String doStringCommandWithoutLogging(String command) {
238         if (DBG) {
239             //GET_NETWORK commands flood the logs
240             if (!command.startsWith("GET_NETWORK")) {
241                 Log.d(mTAG, "doString: [" + command + "]");
242             }
243         }
244         synchronized (mLock) {
245             return doStringCommandNative(mInterfacePrefix + command);
246         }
247     }
248 
ping()249     public boolean ping() {
250         String pong = doStringCommand("PING");
251         return (pong != null && pong.equals("PONG"));
252     }
253 
setSupplicantLogLevel(String level)254     public void setSupplicantLogLevel(String level) {
255         doStringCommand("LOG_LEVEL " + level);
256     }
257 
getFreqCapability()258     public String getFreqCapability() {
259         return doStringCommand("GET_CAPABILITY freq");
260     }
261 
scan(int type, String freqList)262     public boolean scan(int type, String freqList) {
263         if (type == SCAN_WITHOUT_CONNECTION_SETUP) {
264             if (freqList == null) return doBooleanCommand("SCAN TYPE=ONLY");
265             else return doBooleanCommand("SCAN TYPE=ONLY freq=" + freqList);
266         } else if (type == SCAN_WITH_CONNECTION_SETUP) {
267             if (freqList == null) return doBooleanCommand("SCAN");
268             else return doBooleanCommand("SCAN freq=" + freqList);
269         } else {
270             throw new IllegalArgumentException("Invalid scan type");
271         }
272     }
273 
274     /* Does a graceful shutdown of supplicant. Is a common stop function for both p2p and sta.
275      *
276      * Note that underneath we use a harsh-sounding "terminate" supplicant command
277      * for a graceful stop and a mild-sounding "stop" interface
278      * to kill the process
279      */
stopSupplicant()280     public boolean stopSupplicant() {
281         return doBooleanCommand("TERMINATE");
282     }
283 
listNetworks()284     public String listNetworks() {
285         return doStringCommand("LIST_NETWORKS");
286     }
287 
listNetworks(int last_id)288     public String listNetworks(int last_id) {
289         return doStringCommand("LIST_NETWORKS LAST_ID=" + last_id);
290     }
291 
addNetwork()292     public int addNetwork() {
293         return doIntCommand("ADD_NETWORK");
294     }
295 
setNetworkVariable(int netId, String name, String value)296     public boolean setNetworkVariable(int netId, String name, String value) {
297         if (TextUtils.isEmpty(name) || TextUtils.isEmpty(value)) return false;
298         if (name.equals(WifiConfiguration.pskVarName)
299                 || name.equals(WifiEnterpriseConfig.PASSWORD_KEY)) {
300             return doBooleanCommandWithoutLogging("SET_NETWORK " + netId + " " + name + " " + value);
301         } else {
302             return doBooleanCommand("SET_NETWORK " + netId + " " + name + " " + value);
303         }
304     }
305 
getNetworkVariable(int netId, String name)306     public String getNetworkVariable(int netId, String name) {
307         if (TextUtils.isEmpty(name)) return null;
308 
309         // GET_NETWORK will likely flood the logs ...
310         return doStringCommandWithoutLogging("GET_NETWORK " + netId + " " + name);
311     }
312 
removeNetwork(int netId)313     public boolean removeNetwork(int netId) {
314         return doBooleanCommand("REMOVE_NETWORK " + netId);
315     }
316 
317 
logDbg(String debug)318     private void logDbg(String debug) {
319         long now = SystemClock.elapsedRealtimeNanos();
320         String ts = String.format("[%,d us] ", now/1000);
321         Log.e("WifiNative: ", ts+debug+ " stack:"
322                 + Thread.currentThread().getStackTrace()[2].getMethodName() +" - "
323                 + Thread.currentThread().getStackTrace()[3].getMethodName() +" - "
324                 + Thread.currentThread().getStackTrace()[4].getMethodName() +" - "
325                 + Thread.currentThread().getStackTrace()[5].getMethodName()+" - "
326                 + Thread.currentThread().getStackTrace()[6].getMethodName());
327 
328     }
enableNetwork(int netId, boolean disableOthers)329     public boolean enableNetwork(int netId, boolean disableOthers) {
330         if (DBG) logDbg("enableNetwork nid=" + Integer.toString(netId)
331                 + " disableOthers=" + disableOthers);
332         if (disableOthers) {
333             return doBooleanCommand("SELECT_NETWORK " + netId);
334         } else {
335             return doBooleanCommand("ENABLE_NETWORK " + netId);
336         }
337     }
338 
disableNetwork(int netId)339     public boolean disableNetwork(int netId) {
340         if (DBG) logDbg("disableNetwork nid=" + Integer.toString(netId));
341         return doBooleanCommand("DISABLE_NETWORK " + netId);
342     }
343 
selectNetwork(int netId)344     public boolean selectNetwork(int netId) {
345         if (DBG) logDbg("selectNetwork nid=" + Integer.toString(netId));
346         return doBooleanCommand("SELECT_NETWORK " + netId);
347     }
348 
reconnect()349     public boolean reconnect() {
350         if (DBG) logDbg("RECONNECT ");
351         return doBooleanCommand("RECONNECT");
352     }
353 
reassociate()354     public boolean reassociate() {
355         if (DBG) logDbg("REASSOCIATE ");
356         return doBooleanCommand("REASSOCIATE");
357     }
358 
disconnect()359     public boolean disconnect() {
360         if (DBG) logDbg("DISCONNECT ");
361         return doBooleanCommand("DISCONNECT");
362     }
363 
status()364     public String status() {
365         return status(false);
366     }
367 
status(boolean noEvents)368     public String status(boolean noEvents) {
369         if (noEvents) {
370             return doStringCommand("STATUS-NO_EVENTS");
371         } else {
372             return doStringCommand("STATUS");
373         }
374     }
375 
getMacAddress()376     public String getMacAddress() {
377         //Macaddr = XX.XX.XX.XX.XX.XX
378         String ret = doStringCommand("DRIVER MACADDR");
379         if (!TextUtils.isEmpty(ret)) {
380             String[] tokens = ret.split(" = ");
381             if (tokens.length == 2) return tokens[1];
382         }
383         return null;
384     }
385 
386 
387 
388     /**
389      * Format of results:
390      * =================
391      * id=1
392      * bssid=68:7f:74:d7:1b:6e
393      * freq=2412
394      * level=-43
395      * tsf=1344621975160944
396      * age=2623
397      * flags=[WPA2-PSK-CCMP][WPS][ESS]
398      * ssid=zubyb
399      * ====
400      *
401      * RANGE=ALL gets all scan results
402      * RANGE=ID- gets results from ID
403      * MASK=<N> see wpa_supplicant/src/common/wpa_ctrl.h for details
404      * 0                         0                        1                       0     2
405      *                           WPA_BSS_MASK_MESH_SCAN | WPA_BSS_MASK_DELIM    | WPA_BSS_MASK_WIFI_DISPLAY
406      * 0                         0                        0                       1     1   -> 9
407      * WPA_BSS_MASK_INTERNETW  | WPA_BSS_MASK_P2P_SCAN  | WPA_BSS_MASK_WPS_SCAN | WPA_BSS_MASK_SSID
408      * 1                         0                        0                       1     9   -> d
409      * WPA_BSS_MASK_FLAGS      | WPA_BSS_MASK_IE        | WPA_BSS_MASK_AGE      | WPA_BSS_MASK_TSF
410      * 1                         0                        0                       0     8
411      * WPA_BSS_MASK_LEVEL      | WPA_BSS_MASK_NOISE     | WPA_BSS_MASK_QUAL     | WPA_BSS_MASK_CAPABILITIES
412      * 0                         1                        1                       1     7
413      * WPA_BSS_MASK_BEACON_INT | WPA_BSS_MASK_FREQ      | WPA_BSS_MASK_BSSID    | WPA_BSS_MASK_ID
414      *
415      * WPA_BSS_MASK_INTERNETW adds ANQP info (ctrl_iface:4151-4176)
416      *
417      * ctrl_iface.c:wpa_supplicant_ctrl_iface_process:7884
418      *  wpa_supplicant_ctrl_iface_bss:4315
419      *  print_bss_info
420      */
scanResults(int sid)421     public String scanResults(int sid) {
422         return doStringCommandWithoutLogging("BSS RANGE=" + sid + "- MASK=0x29d87");
423     }
424 
doCustomCommand(String command)425     public String doCustomCommand(String command) {
426         return doStringCommand(command);
427     }
428 
429     /**
430      * Format of result:
431      * id=1016
432      * bssid=00:03:7f:40:84:10
433      * freq=2462
434      * beacon_int=200
435      * capabilities=0x0431
436      * qual=0
437      * noise=0
438      * level=-46
439      * tsf=0000002669008476
440      * age=5
441      * ie=00105143412d485332302d52322d54455354010882848b960c12182403010b0706555...
442      * flags=[WPA2-EAP-CCMP][ESS][P2P][HS20]
443      * ssid=QCA-HS20-R2-TEST
444      * p2p_device_name=
445      * p2p_config_methods=0x0SET_NE
446      * anqp_venue_name=02083d656e6757692d466920416c6c69616e63650a3239383920436f...
447      * anqp_network_auth_type=010000
448      * anqp_roaming_consortium=03506f9a05001bc504bd
449      * anqp_ip_addr_type_availability=0c
450      * anqp_nai_realm=0200300000246d61696c2e6578616d706c652e636f6d3b636973636f2...
451      * anqp_3gpp=000600040132f465
452      * anqp_domain_name=0b65786d61706c652e636f6d
453      * hs20_operator_friendly_name=11656e6757692d466920416c6c69616e63650e636869...
454      * hs20_wan_metrics=01c40900008001000000000a00
455      * hs20_connection_capability=0100000006140001061600000650000106bb010106bb0...
456      * hs20_osu_providers_list=0b5143412d4f53552d425353010901310015656e6757692d...
457      */
scanResult(String bssid)458     public String scanResult(String bssid) {
459         return doStringCommand("BSS " + bssid);
460     }
461 
462     /**
463      * Format of command
464      * DRIVER WLS_BATCHING SET SCANFREQ=x MSCAN=r BESTN=y CHANNEL=<z, w, t> RTT=s
465      * where x is an ascii representation of an integer number of seconds between scans
466      *       r is an ascii representation of an integer number of scans per batch
467      *       y is an ascii representation of an integer number of the max AP to remember per scan
468      *       z, w, t represent a 1..n size list of channel numbers and/or 'A', 'B' values
469      *           indicating entire ranges of channels
470      *       s is an ascii representation of an integer number of highest-strength AP
471      *           for which we'd like approximate distance reported
472      *
473      * The return value is an ascii integer representing a guess of the number of scans
474      * the firmware can remember before it runs out of buffer space or -1 on error
475      */
setBatchedScanSettings(BatchedScanSettings settings)476     public String setBatchedScanSettings(BatchedScanSettings settings) {
477         if (settings == null) {
478             return doStringCommand("DRIVER WLS_BATCHING STOP");
479         }
480         String cmd = "DRIVER WLS_BATCHING SET SCANFREQ=" + settings.scanIntervalSec;
481         cmd += " MSCAN=" + settings.maxScansPerBatch;
482         if (settings.maxApPerScan != BatchedScanSettings.UNSPECIFIED) {
483             cmd += " BESTN=" + settings.maxApPerScan;
484         }
485         if (settings.channelSet != null && !settings.channelSet.isEmpty()) {
486             cmd += " CHANNEL=<";
487             int i = 0;
488             for (String channel : settings.channelSet) {
489                 cmd += (i > 0 ? "," : "") + channel;
490                 ++i;
491             }
492             cmd += ">";
493         }
494         if (settings.maxApForDistance != BatchedScanSettings.UNSPECIFIED) {
495             cmd += " RTT=" + settings.maxApForDistance;
496         }
497         return doStringCommand(cmd);
498     }
499 
getBatchedScanResults()500     public String getBatchedScanResults() {
501         return doStringCommand("DRIVER WLS_BATCHING GET");
502     }
503 
startDriver()504     public boolean startDriver() {
505         return doBooleanCommand("DRIVER START");
506     }
507 
stopDriver()508     public boolean stopDriver() {
509         return doBooleanCommand("DRIVER STOP");
510     }
511 
512 
513     /**
514      * Start filtering out Multicast V4 packets
515      * @return {@code true} if the operation succeeded, {@code false} otherwise
516      *
517      * Multicast filtering rules work as follows:
518      *
519      * The driver can filter multicast (v4 and/or v6) and broadcast packets when in
520      * a power optimized mode (typically when screen goes off).
521      *
522      * In order to prevent the driver from filtering the multicast/broadcast packets, we have to
523      * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective
524      *
525      * DRIVER RXFILTER-ADD Num
526      *   where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6
527      *
528      * and DRIVER RXFILTER-START
529      * In order to stop the usage of these rules, we do
530      *
531      * DRIVER RXFILTER-STOP
532      * DRIVER RXFILTER-REMOVE Num
533      *   where Num is as described for RXFILTER-ADD
534      *
535      * The  SETSUSPENDOPT driver command overrides the filtering rules
536      */
startFilteringMulticastV4Packets()537     public boolean startFilteringMulticastV4Packets() {
538         return doBooleanCommand("DRIVER RXFILTER-STOP")
539             && doBooleanCommand("DRIVER RXFILTER-REMOVE 2")
540             && doBooleanCommand("DRIVER RXFILTER-START");
541     }
542 
543     /**
544      * Stop filtering out Multicast V4 packets.
545      * @return {@code true} if the operation succeeded, {@code false} otherwise
546      */
stopFilteringMulticastV4Packets()547     public boolean stopFilteringMulticastV4Packets() {
548         return doBooleanCommand("DRIVER RXFILTER-STOP")
549             && doBooleanCommand("DRIVER RXFILTER-ADD 2")
550             && doBooleanCommand("DRIVER RXFILTER-START");
551     }
552 
553     /**
554      * Start filtering out Multicast V6 packets
555      * @return {@code true} if the operation succeeded, {@code false} otherwise
556      */
startFilteringMulticastV6Packets()557     public boolean startFilteringMulticastV6Packets() {
558         return doBooleanCommand("DRIVER RXFILTER-STOP")
559             && doBooleanCommand("DRIVER RXFILTER-REMOVE 3")
560             && doBooleanCommand("DRIVER RXFILTER-START");
561     }
562 
563     /**
564      * Stop filtering out Multicast V6 packets.
565      * @return {@code true} if the operation succeeded, {@code false} otherwise
566      */
stopFilteringMulticastV6Packets()567     public boolean stopFilteringMulticastV6Packets() {
568         return doBooleanCommand("DRIVER RXFILTER-STOP")
569             && doBooleanCommand("DRIVER RXFILTER-ADD 3")
570             && doBooleanCommand("DRIVER RXFILTER-START");
571     }
572 
573     /**
574      * Set the operational frequency band
575      * @param band One of
576      *     {@link WifiManager#WIFI_FREQUENCY_BAND_AUTO},
577      *     {@link WifiManager#WIFI_FREQUENCY_BAND_5GHZ},
578      *     {@link WifiManager#WIFI_FREQUENCY_BAND_2GHZ},
579      * @return {@code true} if the operation succeeded, {@code false} otherwise
580      */
setBand(int band)581     public boolean setBand(int band) {
582         String bandstr;
583 
584         if (band == WifiManager.WIFI_FREQUENCY_BAND_5GHZ)
585             bandstr = "5G";
586         else if (band == WifiManager.WIFI_FREQUENCY_BAND_2GHZ)
587             bandstr = "2G";
588         else
589             bandstr = "AUTO";
590         return doBooleanCommand("SET SETBAND " + bandstr);
591     }
592 
593     /**
594       * Sets the bluetooth coexistence mode.
595       *
596       * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED},
597       *            {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or
598       *            {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}.
599       * @return Whether the mode was successfully set.
600       */
setBluetoothCoexistenceMode(int mode)601     public boolean setBluetoothCoexistenceMode(int mode) {
602         return doBooleanCommand("DRIVER BTCOEXMODE " + mode);
603     }
604 
605     /**
606      * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
607      * some of the low-level scan parameters used by the driver are changed to
608      * reduce interference with A2DP streaming.
609      *
610      * @param isSet whether to enable or disable this mode
611      * @return {@code true} if the command succeeded, {@code false} otherwise.
612      */
setBluetoothCoexistenceScanMode(boolean setCoexScanMode)613     public boolean setBluetoothCoexistenceScanMode(boolean setCoexScanMode) {
614         if (setCoexScanMode) {
615             return doBooleanCommand("DRIVER BTCOEXSCAN-START");
616         } else {
617             return doBooleanCommand("DRIVER BTCOEXSCAN-STOP");
618         }
619     }
620 
enableSaveConfig()621     public void enableSaveConfig() {
622         doBooleanCommand("SET update_config 1");
623     }
624 
saveConfig()625     public boolean saveConfig() {
626         return doBooleanCommand("SAVE_CONFIG");
627     }
628 
addToBlacklist(String bssid)629     public boolean addToBlacklist(String bssid) {
630         if (TextUtils.isEmpty(bssid)) return false;
631         return doBooleanCommand("BLACKLIST " + bssid);
632     }
633 
clearBlacklist()634     public boolean clearBlacklist() {
635         return doBooleanCommand("BLACKLIST clear");
636     }
637 
setSuspendOptimizations(boolean enabled)638     public boolean setSuspendOptimizations(boolean enabled) {
639        // if (mSuspendOptEnabled == enabled) return true;
640         mSuspendOptEnabled = enabled;
641 
642         Log.e("native", "do suspend " + enabled);
643         if (enabled) {
644             return doBooleanCommand("DRIVER SETSUSPENDMODE 1");
645         } else {
646             return doBooleanCommand("DRIVER SETSUSPENDMODE 0");
647         }
648     }
649 
setCountryCode(String countryCode)650     public boolean setCountryCode(String countryCode) {
651         if (countryCode != null)
652             return doBooleanCommand("DRIVER COUNTRY " + countryCode.toUpperCase(Locale.ROOT));
653         else
654             return doBooleanCommand("DRIVER COUNTRY");
655     }
656 
enableBackgroundScan(boolean enable)657     public boolean enableBackgroundScan(boolean enable) {
658         boolean ret;
659         if (enable) {
660             ret = doBooleanCommand("SET pno 1");
661         } else {
662             ret = doBooleanCommand("SET pno 0");
663         }
664         return ret;
665     }
666 
enableAutoConnect(boolean enable)667     public void enableAutoConnect(boolean enable) {
668         if (enable) {
669             doBooleanCommand("STA_AUTOCONNECT 1");
670         } else {
671             doBooleanCommand("STA_AUTOCONNECT 0");
672         }
673     }
674 
setScanInterval(int scanInterval)675     public void setScanInterval(int scanInterval) {
676         doBooleanCommand("SCAN_INTERVAL " + scanInterval);
677     }
678 
startTdls(String macAddr, boolean enable)679     public void startTdls(String macAddr, boolean enable) {
680         if (enable) {
681             doBooleanCommand("TDLS_DISCOVER " + macAddr);
682             doBooleanCommand("TDLS_SETUP " + macAddr);
683         } else {
684             doBooleanCommand("TDLS_TEARDOWN " + macAddr);
685         }
686     }
687 
688     /** Example output:
689      * RSSI=-65
690      * LINKSPEED=48
691      * NOISE=9999
692      * FREQUENCY=0
693      */
signalPoll()694     public String signalPoll() {
695         return doStringCommandWithoutLogging("SIGNAL_POLL");
696     }
697 
698     /** Example outout:
699      * TXGOOD=396
700      * TXBAD=1
701      */
pktcntPoll()702     public String pktcntPoll() {
703         return doStringCommand("PKTCNT_POLL");
704     }
705 
bssFlush()706     public void bssFlush() {
707         doBooleanCommand("BSS_FLUSH 0");
708     }
709 
startWpsPbc(String bssid)710     public boolean startWpsPbc(String bssid) {
711         if (TextUtils.isEmpty(bssid)) {
712             return doBooleanCommand("WPS_PBC");
713         } else {
714             return doBooleanCommand("WPS_PBC " + bssid);
715         }
716     }
717 
startWpsPbc(String iface, String bssid)718     public boolean startWpsPbc(String iface, String bssid) {
719         synchronized (mLock) {
720             if (TextUtils.isEmpty(bssid)) {
721                 return doBooleanCommandNative("IFNAME=" + iface + " WPS_PBC");
722             } else {
723                 return doBooleanCommandNative("IFNAME=" + iface + " WPS_PBC " + bssid);
724             }
725         }
726     }
727 
startWpsPinKeypad(String pin)728     public boolean startWpsPinKeypad(String pin) {
729         if (TextUtils.isEmpty(pin)) return false;
730         return doBooleanCommand("WPS_PIN any " + pin);
731     }
732 
startWpsPinKeypad(String iface, String pin)733     public boolean startWpsPinKeypad(String iface, String pin) {
734         if (TextUtils.isEmpty(pin)) return false;
735         synchronized (mLock) {
736             return doBooleanCommandNative("IFNAME=" + iface + " WPS_PIN any " + pin);
737         }
738     }
739 
740 
startWpsPinDisplay(String bssid)741     public String startWpsPinDisplay(String bssid) {
742         if (TextUtils.isEmpty(bssid)) {
743             return doStringCommand("WPS_PIN any");
744         } else {
745             return doStringCommand("WPS_PIN " + bssid);
746         }
747     }
748 
startWpsPinDisplay(String iface, String bssid)749     public String startWpsPinDisplay(String iface, String bssid) {
750         synchronized (mLock) {
751             if (TextUtils.isEmpty(bssid)) {
752                 return doStringCommandNative("IFNAME=" + iface + " WPS_PIN any");
753             } else {
754                 return doStringCommandNative("IFNAME=" + iface + " WPS_PIN " + bssid);
755             }
756         }
757     }
758 
setExternalSim(boolean external)759     public boolean setExternalSim(boolean external) {
760         synchronized (mLock) {
761             String value = external ? "1" : "0";
762             Log.d(TAG, "Setting external_sim to " + value);
763             return doBooleanCommand("SET external_sim " + value);
764         }
765     }
766 
simAuthResponse(int id, String type, String response)767     public boolean simAuthResponse(int id, String type, String response) {
768         // with type = GSM-AUTH, UMTS-AUTH or UMTS-AUTS
769         synchronized (mLock) {
770             return doBooleanCommand("CTRL-RSP-SIM-" + id + ":" + type + response);
771         }
772     }
773 
simIdentityResponse(int id, String response)774     public boolean simIdentityResponse(int id, String response) {
775         synchronized (mLock) {
776             return doBooleanCommand("CTRL-RSP-IDENTITY-" + id + ":" + response);
777         }
778     }
779 
780     /* Configures an access point connection */
startWpsRegistrar(String bssid, String pin)781     public boolean startWpsRegistrar(String bssid, String pin) {
782         if (TextUtils.isEmpty(bssid) || TextUtils.isEmpty(pin)) return false;
783         return doBooleanCommand("WPS_REG " + bssid + " " + pin);
784     }
785 
cancelWps()786     public boolean cancelWps() {
787         return doBooleanCommand("WPS_CANCEL");
788     }
789 
setPersistentReconnect(boolean enabled)790     public boolean setPersistentReconnect(boolean enabled) {
791         int value = (enabled == true) ? 1 : 0;
792         return doBooleanCommand("SET persistent_reconnect " + value);
793     }
794 
setDeviceName(String name)795     public boolean setDeviceName(String name) {
796         return doBooleanCommand("SET device_name " + name);
797     }
798 
setDeviceType(String type)799     public boolean setDeviceType(String type) {
800         return doBooleanCommand("SET device_type " + type);
801     }
802 
setConfigMethods(String cfg)803     public boolean setConfigMethods(String cfg) {
804         return doBooleanCommand("SET config_methods " + cfg);
805     }
806 
setManufacturer(String value)807     public boolean setManufacturer(String value) {
808         return doBooleanCommand("SET manufacturer " + value);
809     }
810 
setModelName(String value)811     public boolean setModelName(String value) {
812         return doBooleanCommand("SET model_name " + value);
813     }
814 
setModelNumber(String value)815     public boolean setModelNumber(String value) {
816         return doBooleanCommand("SET model_number " + value);
817     }
818 
setSerialNumber(String value)819     public boolean setSerialNumber(String value) {
820         return doBooleanCommand("SET serial_number " + value);
821     }
822 
setP2pSsidPostfix(String postfix)823     public boolean setP2pSsidPostfix(String postfix) {
824         return doBooleanCommand("SET p2p_ssid_postfix " + postfix);
825     }
826 
setP2pGroupIdle(String iface, int time)827     public boolean setP2pGroupIdle(String iface, int time) {
828         synchronized (mLock) {
829             return doBooleanCommandNative("IFNAME=" + iface + " SET p2p_group_idle " + time);
830         }
831     }
832 
setPowerSave(boolean enabled)833     public void setPowerSave(boolean enabled) {
834         if (enabled) {
835             doBooleanCommand("SET ps 1");
836         } else {
837             doBooleanCommand("SET ps 0");
838         }
839     }
840 
setP2pPowerSave(String iface, boolean enabled)841     public boolean setP2pPowerSave(String iface, boolean enabled) {
842         synchronized (mLock) {
843             if (enabled) {
844                 return doBooleanCommandNative("IFNAME=" + iface + " P2P_SET ps 1");
845             } else {
846                 return doBooleanCommandNative("IFNAME=" + iface + " P2P_SET ps 0");
847             }
848         }
849     }
850 
setWfdEnable(boolean enable)851     public boolean setWfdEnable(boolean enable) {
852         return doBooleanCommand("SET wifi_display " + (enable ? "1" : "0"));
853     }
854 
setWfdDeviceInfo(String hex)855     public boolean setWfdDeviceInfo(String hex) {
856         return doBooleanCommand("WFD_SUBELEM_SET 0 " + hex);
857     }
858 
859     /**
860      * "sta" prioritizes STA connection over P2P and "p2p" prioritizes
861      * P2P connection over STA
862      */
setConcurrencyPriority(String s)863     public boolean setConcurrencyPriority(String s) {
864         return doBooleanCommand("P2P_SET conc_pref " + s);
865     }
866 
p2pFind()867     public boolean p2pFind() {
868         return doBooleanCommand("P2P_FIND");
869     }
870 
p2pFind(int timeout)871     public boolean p2pFind(int timeout) {
872         if (timeout <= 0) {
873             return p2pFind();
874         }
875         return doBooleanCommand("P2P_FIND " + timeout);
876     }
877 
p2pStopFind()878     public boolean p2pStopFind() {
879        return doBooleanCommand("P2P_STOP_FIND");
880     }
881 
p2pListen()882     public boolean p2pListen() {
883         return doBooleanCommand("P2P_LISTEN");
884     }
885 
p2pListen(int timeout)886     public boolean p2pListen(int timeout) {
887         if (timeout <= 0) {
888             return p2pListen();
889         }
890         return doBooleanCommand("P2P_LISTEN " + timeout);
891     }
892 
p2pExtListen(boolean enable, int period, int interval)893     public boolean p2pExtListen(boolean enable, int period, int interval) {
894         if (enable && interval < period) {
895             return false;
896         }
897         return doBooleanCommand("P2P_EXT_LISTEN"
898                     + (enable ? (" " + period + " " + interval) : ""));
899     }
900 
p2pSetChannel(int lc, int oc)901     public boolean p2pSetChannel(int lc, int oc) {
902         if (DBG) Log.d(mTAG, "p2pSetChannel: lc="+lc+", oc="+oc);
903 
904         if (lc >=1 && lc <= 11) {
905             if (!doBooleanCommand("P2P_SET listen_channel " + lc)) {
906                 return false;
907             }
908         } else if (lc != 0) {
909             return false;
910         }
911 
912         if (oc >= 1 && oc <= 165 ) {
913             int freq = (oc <= 14 ? 2407 : 5000) + oc * 5;
914             return doBooleanCommand("P2P_SET disallow_freq 1000-"
915                     + (freq - 5) + "," + (freq + 5) + "-6000");
916         } else if (oc == 0) {
917             /* oc==0 disables "P2P_SET disallow_freq" (enables all freqs) */
918             return doBooleanCommand("P2P_SET disallow_freq \"\"");
919         }
920 
921         return false;
922     }
923 
p2pFlush()924     public boolean p2pFlush() {
925         return doBooleanCommand("P2P_FLUSH");
926     }
927 
928     /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad]
929         [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] */
p2pConnect(WifiP2pConfig config, boolean joinExistingGroup)930     public String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) {
931         if (config == null) return null;
932         List<String> args = new ArrayList<String>();
933         WpsInfo wps = config.wps;
934         args.add(config.deviceAddress);
935 
936         switch (wps.setup) {
937             case WpsInfo.PBC:
938                 args.add("pbc");
939                 break;
940             case WpsInfo.DISPLAY:
941                 if (TextUtils.isEmpty(wps.pin)) {
942                     args.add("pin");
943                 } else {
944                     args.add(wps.pin);
945                 }
946                 args.add("display");
947                 break;
948             case WpsInfo.KEYPAD:
949                 args.add(wps.pin);
950                 args.add("keypad");
951                 break;
952             case WpsInfo.LABEL:
953                 args.add(wps.pin);
954                 args.add("label");
955             default:
956                 break;
957         }
958 
959         if (config.netId == WifiP2pGroup.PERSISTENT_NET_ID) {
960             args.add("persistent");
961         }
962 
963         if (joinExistingGroup) {
964             args.add("join");
965         } else {
966             //TODO: This can be adapted based on device plugged in state and
967             //device battery state
968             int groupOwnerIntent = config.groupOwnerIntent;
969             if (groupOwnerIntent < 0 || groupOwnerIntent > 15) {
970                 groupOwnerIntent = DEFAULT_GROUP_OWNER_INTENT;
971             }
972             args.add("go_intent=" + groupOwnerIntent);
973         }
974 
975         String command = "P2P_CONNECT ";
976         for (String s : args) command += s + " ";
977 
978         return doStringCommand(command);
979     }
980 
p2pCancelConnect()981     public boolean p2pCancelConnect() {
982         return doBooleanCommand("P2P_CANCEL");
983     }
984 
p2pProvisionDiscovery(WifiP2pConfig config)985     public boolean p2pProvisionDiscovery(WifiP2pConfig config) {
986         if (config == null) return false;
987 
988         switch (config.wps.setup) {
989             case WpsInfo.PBC:
990                 return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " pbc");
991             case WpsInfo.DISPLAY:
992                 //We are doing display, so provision discovery is keypad
993                 return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " keypad");
994             case WpsInfo.KEYPAD:
995                 //We are doing keypad, so provision discovery is display
996                 return doBooleanCommand("P2P_PROV_DISC " + config.deviceAddress + " display");
997             default:
998                 break;
999         }
1000         return false;
1001     }
1002 
p2pGroupAdd(boolean persistent)1003     public boolean p2pGroupAdd(boolean persistent) {
1004         if (persistent) {
1005             return doBooleanCommand("P2P_GROUP_ADD persistent");
1006         }
1007         return doBooleanCommand("P2P_GROUP_ADD");
1008     }
1009 
p2pGroupAdd(int netId)1010     public boolean p2pGroupAdd(int netId) {
1011         return doBooleanCommand("P2P_GROUP_ADD persistent=" + netId);
1012     }
1013 
p2pGroupRemove(String iface)1014     public boolean p2pGroupRemove(String iface) {
1015         if (TextUtils.isEmpty(iface)) return false;
1016         synchronized (mLock) {
1017             return doBooleanCommandNative("IFNAME=" + iface + " P2P_GROUP_REMOVE " + iface);
1018         }
1019     }
1020 
p2pReject(String deviceAddress)1021     public boolean p2pReject(String deviceAddress) {
1022         return doBooleanCommand("P2P_REJECT " + deviceAddress);
1023     }
1024 
1025     /* Invite a peer to a group */
p2pInvite(WifiP2pGroup group, String deviceAddress)1026     public boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
1027         if (TextUtils.isEmpty(deviceAddress)) return false;
1028 
1029         if (group == null) {
1030             return doBooleanCommand("P2P_INVITE peer=" + deviceAddress);
1031         } else {
1032             return doBooleanCommand("P2P_INVITE group=" + group.getInterface()
1033                     + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress);
1034         }
1035     }
1036 
1037     /* Reinvoke a persistent connection */
p2pReinvoke(int netId, String deviceAddress)1038     public boolean p2pReinvoke(int netId, String deviceAddress) {
1039         if (TextUtils.isEmpty(deviceAddress) || netId < 0) return false;
1040 
1041         return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress);
1042     }
1043 
p2pGetSsid(String deviceAddress)1044     public String p2pGetSsid(String deviceAddress) {
1045         return p2pGetParam(deviceAddress, "oper_ssid");
1046     }
1047 
p2pGetDeviceAddress()1048     public String p2pGetDeviceAddress() {
1049 
1050         Log.d(TAG, "p2pGetDeviceAddress");
1051 
1052         String status = null;
1053 
1054         /* Explicitly calling the API without IFNAME= prefix to take care of the devices that
1055         don't have p2p0 interface. Supplicant seems to be returning the correct address anyway. */
1056 
1057         synchronized (mLock) {
1058             status = doStringCommandNative("STATUS");
1059         }
1060 
1061         String result = "";
1062         if (status != null) {
1063             String[] tokens = status.split("\n");
1064             for (String token : tokens) {
1065                 if (token.startsWith("p2p_device_address=")) {
1066                     String[] nameValue = token.split("=");
1067                     if (nameValue.length != 2)
1068                         break;
1069                     result = nameValue[1];
1070                 }
1071             }
1072         }
1073 
1074         Log.d(TAG, "p2pGetDeviceAddress returning " + result);
1075         return result;
1076     }
1077 
getGroupCapability(String deviceAddress)1078     public int getGroupCapability(String deviceAddress) {
1079         int gc = 0;
1080         if (TextUtils.isEmpty(deviceAddress)) return gc;
1081         String peerInfo = p2pPeer(deviceAddress);
1082         if (TextUtils.isEmpty(peerInfo)) return gc;
1083 
1084         String[] tokens = peerInfo.split("\n");
1085         for (String token : tokens) {
1086             if (token.startsWith("group_capab=")) {
1087                 String[] nameValue = token.split("=");
1088                 if (nameValue.length != 2) break;
1089                 try {
1090                     return Integer.decode(nameValue[1]);
1091                 } catch(NumberFormatException e) {
1092                     return gc;
1093                 }
1094             }
1095         }
1096         return gc;
1097     }
1098 
p2pPeer(String deviceAddress)1099     public String p2pPeer(String deviceAddress) {
1100         return doStringCommand("P2P_PEER " + deviceAddress);
1101     }
1102 
p2pGetParam(String deviceAddress, String key)1103     private String p2pGetParam(String deviceAddress, String key) {
1104         if (deviceAddress == null) return null;
1105 
1106         String peerInfo = p2pPeer(deviceAddress);
1107         if (peerInfo == null) return null;
1108         String[] tokens= peerInfo.split("\n");
1109 
1110         key += "=";
1111         for (String token : tokens) {
1112             if (token.startsWith(key)) {
1113                 String[] nameValue = token.split("=");
1114                 if (nameValue.length != 2) break;
1115                 return nameValue[1];
1116             }
1117         }
1118         return null;
1119     }
1120 
p2pServiceAdd(WifiP2pServiceInfo servInfo)1121     public boolean p2pServiceAdd(WifiP2pServiceInfo servInfo) {
1122         /*
1123          * P2P_SERVICE_ADD bonjour <query hexdump> <RDATA hexdump>
1124          * P2P_SERVICE_ADD upnp <version hex> <service>
1125          *
1126          * e.g)
1127          * [Bonjour]
1128          * # IP Printing over TCP (PTR) (RDATA=MyPrinter._ipp._tcp.local.)
1129          * P2P_SERVICE_ADD bonjour 045f697070c00c000c01 094d795072696e746572c027
1130          * # IP Printing over TCP (TXT) (RDATA=txtvers=1,pdl=application/postscript)
1131          * P2P_SERVICE_ADD bonjour 096d797072696e746572045f697070c00c001001
1132          *  09747874766572733d311a70646c3d6170706c69636174696f6e2f706f7374736372797074
1133          *
1134          * [UPnP]
1135          * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012
1136          * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::upnp:rootdevice
1137          * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnp
1138          * -org:device:InternetGatewayDevice:1
1139          * P2P_SERVICE_ADD upnp 10 uuid:6859dede-8574-59ab-9322-123456789012::urn:schemas-upnp
1140          * -org:service:ContentDirectory:2
1141          */
1142         for (String s : servInfo.getSupplicantQueryList()) {
1143             String command = "P2P_SERVICE_ADD";
1144             command += (" " + s);
1145             if (!doBooleanCommand(command)) {
1146                 return false;
1147             }
1148         }
1149         return true;
1150     }
1151 
p2pServiceDel(WifiP2pServiceInfo servInfo)1152     public boolean p2pServiceDel(WifiP2pServiceInfo servInfo) {
1153         /*
1154          * P2P_SERVICE_DEL bonjour <query hexdump>
1155          * P2P_SERVICE_DEL upnp <version hex> <service>
1156          */
1157         for (String s : servInfo.getSupplicantQueryList()) {
1158             String command = "P2P_SERVICE_DEL ";
1159 
1160             String[] data = s.split(" ");
1161             if (data.length < 2) {
1162                 return false;
1163             }
1164             if ("upnp".equals(data[0])) {
1165                 command += s;
1166             } else if ("bonjour".equals(data[0])) {
1167                 command += data[0];
1168                 command += (" " + data[1]);
1169             } else {
1170                 return false;
1171             }
1172             if (!doBooleanCommand(command)) {
1173                 return false;
1174             }
1175         }
1176         return true;
1177     }
1178 
p2pServiceFlush()1179     public boolean p2pServiceFlush() {
1180         return doBooleanCommand("P2P_SERVICE_FLUSH");
1181     }
1182 
p2pServDiscReq(String addr, String query)1183     public String p2pServDiscReq(String addr, String query) {
1184         String command = "P2P_SERV_DISC_REQ";
1185         command += (" " + addr);
1186         command += (" " + query);
1187 
1188         return doStringCommand(command);
1189     }
1190 
p2pServDiscCancelReq(String id)1191     public boolean p2pServDiscCancelReq(String id) {
1192         return doBooleanCommand("P2P_SERV_DISC_CANCEL_REQ " + id);
1193     }
1194 
1195     /* Set the current mode of miracast operation.
1196      *  0 = disabled
1197      *  1 = operating as source
1198      *  2 = operating as sink
1199      */
setMiracastMode(int mode)1200     public void setMiracastMode(int mode) {
1201         // Note: optional feature on the driver. It is ok for this to fail.
1202         doBooleanCommand("DRIVER MIRACAST " + mode);
1203     }
1204 
fetchAnqp(String bssid, String subtypes)1205     public boolean fetchAnqp(String bssid, String subtypes) {
1206         return doBooleanCommand("ANQP_GET " + bssid + " " + subtypes);
1207     }
1208 
1209     /*
1210      * NFC-related calls
1211      */
getNfcWpsConfigurationToken(int netId)1212     public String getNfcWpsConfigurationToken(int netId) {
1213         return doStringCommand("WPS_NFC_CONFIG_TOKEN WPS " + netId);
1214     }
1215 
getNfcHandoverRequest()1216     public String getNfcHandoverRequest() {
1217         return doStringCommand("NFC_GET_HANDOVER_REQ NDEF P2P-CR");
1218     }
1219 
getNfcHandoverSelect()1220     public String getNfcHandoverSelect() {
1221         return doStringCommand("NFC_GET_HANDOVER_SEL NDEF P2P-CR");
1222     }
1223 
initiatorReportNfcHandover(String selectMessage)1224     public boolean initiatorReportNfcHandover(String selectMessage) {
1225         return doBooleanCommand("NFC_REPORT_HANDOVER INIT P2P 00 " + selectMessage);
1226     }
1227 
responderReportNfcHandover(String requestMessage)1228     public boolean responderReportNfcHandover(String requestMessage) {
1229         return doBooleanCommand("NFC_REPORT_HANDOVER RESP P2P " + requestMessage + " 00");
1230     }
1231 
1232     /* WIFI HAL support */
1233 
1234     private static final String TAG = "WifiNative-HAL";
1235     private static long sWifiHalHandle = 0;             /* used by JNI to save wifi_handle */
1236     private static long[] sWifiIfaceHandles = null;     /* used by JNI to save interface handles */
1237     private static int sWlan0Index = -1;
1238     private static int sP2p0Index = -1;
1239     private static MonitorThread sThread;
1240     private static final int STOP_HAL_TIMEOUT_MS = 1000;
1241 
startHalNative()1242     private static native boolean startHalNative();
stopHalNative()1243     private static native void stopHalNative();
waitForHalEventNative()1244     private static native void waitForHalEventNative();
1245 
1246     private static class MonitorThread extends Thread {
run()1247         public void run() {
1248             Log.i(TAG, "Waiting for HAL events mWifiHalHandle=" + Long.toString(sWifiHalHandle));
1249             waitForHalEventNative();
1250         }
1251     }
1252 
startHal()1253     synchronized public static boolean startHal() {
1254 
1255         String debugLog = "startHal stack: ";
1256         java.lang.StackTraceElement[] elements = Thread.currentThread().getStackTrace();
1257         for (int i = 2; i < elements.length && i <= 7; i++ ) {
1258             debugLog = debugLog + " - " + elements[i].getMethodName();
1259         }
1260 
1261         mLocalLog.log(debugLog);
1262 
1263         synchronized (mLock) {
1264             if (startHalNative() && (getInterfaces() != 0) && (sWlan0Index != -1)) {
1265                 sThread = new MonitorThread();
1266                 sThread.start();
1267                 return true;
1268             } else {
1269                 if (DBG) mLocalLog.log("Could not start hal");
1270                 Log.e(TAG, "Could not start hal");
1271                 return false;
1272             }
1273         }
1274     }
1275 
stopHal()1276     synchronized public static void stopHal() {
1277         synchronized (mLock) {
1278             if (isHalStarted()) {
1279                 stopHalNative();
1280                 try {
1281                     sThread.join(STOP_HAL_TIMEOUT_MS);
1282                     Log.d(TAG, "HAL event thread stopped successfully");
1283                 } catch (InterruptedException e) {
1284                     Log.e(TAG, "Could not stop HAL cleanly");
1285                 }
1286                 sThread = null;
1287                 sWifiHalHandle = 0;
1288                 sWifiIfaceHandles = null;
1289                 sWlan0Index = -1;
1290                 sP2p0Index = -1;
1291             }
1292         }
1293     }
1294 
isHalStarted()1295     public static boolean isHalStarted() {
1296         return (sWifiHalHandle != 0);
1297     }
getInterfacesNative()1298     private static native int getInterfacesNative();
1299 
getInterfaces()1300     synchronized public static int getInterfaces() {
1301         synchronized (mLock) {
1302             if (isHalStarted()) {
1303                 if (sWifiIfaceHandles == null) {
1304                     int num = getInterfacesNative();
1305                     int wifi_num = 0;
1306                     for (int i = 0; i < num; i++) {
1307                         String name = getInterfaceNameNative(i);
1308                         Log.i(TAG, "interface[" + i + "] = " + name);
1309                         if (name.equals("wlan0")) {
1310                             sWlan0Index = i;
1311                             wifi_num++;
1312                         } else if (name.equals("p2p0")) {
1313                             sP2p0Index = i;
1314                             wifi_num++;
1315                         }
1316                     }
1317                     return wifi_num;
1318                 } else {
1319                     return sWifiIfaceHandles.length;
1320                 }
1321             } else {
1322                 return 0;
1323             }
1324         }
1325     }
1326 
getInterfaceNameNative(int index)1327     private static native String getInterfaceNameNative(int index);
getInterfaceName(int index)1328     synchronized public static String getInterfaceName(int index) {
1329         return getInterfaceNameNative(index);
1330     }
1331 
1332     public static class ScanCapabilities {
1333         public int  max_scan_cache_size;                 // in number of scan results??
1334         public int  max_scan_buckets;
1335         public int  max_ap_cache_per_scan;
1336         public int  max_rssi_sample_size;
1337         public int  max_scan_reporting_threshold;        // in number of scan results??
1338         public int  max_hotlist_bssids;
1339         public int  max_significant_wifi_change_aps;
1340     }
1341 
getScanCapabilities(ScanCapabilities capabilities)1342     synchronized public static boolean getScanCapabilities(ScanCapabilities capabilities) {
1343         synchronized (mLock) {
1344             return isHalStarted() && getScanCapabilitiesNative(sWlan0Index, capabilities);
1345         }
1346     }
1347 
getScanCapabilitiesNative( int iface, ScanCapabilities capabilities)1348     private static native boolean getScanCapabilitiesNative(
1349             int iface, ScanCapabilities capabilities);
1350 
startScanNative(int iface, int id, ScanSettings settings)1351     private static native boolean startScanNative(int iface, int id, ScanSettings settings);
stopScanNative(int iface, int id)1352     private static native boolean stopScanNative(int iface, int id);
getScanResultsNative(int iface, boolean flush)1353     private static native WifiScanner.ScanData[] getScanResultsNative(int iface, boolean flush);
getWifiLinkLayerStatsNative(int iface)1354     private static native WifiLinkLayerStats getWifiLinkLayerStatsNative(int iface);
setWifiLinkLayerStatsNative(int iface, int enable)1355     private static native void setWifiLinkLayerStatsNative(int iface, int enable);
1356 
1357     public static class ChannelSettings {
1358         int frequency;
1359         int dwell_time_ms;
1360         boolean passive;
1361     }
1362 
1363     public static class BucketSettings {
1364         int bucket;
1365         int band;
1366         int period_ms;
1367         int report_events;
1368         int num_channels;
1369         ChannelSettings channels[];
1370     }
1371 
1372     public static class ScanSettings {
1373         int base_period_ms;
1374         int max_ap_per_scan;
1375         int report_threshold_percent;
1376         int report_threshold_num_scans;
1377         int num_buckets;
1378         BucketSettings buckets[];
1379     }
1380 
1381     public static interface ScanEventHandler {
onScanResultsAvailable()1382         void onScanResultsAvailable();
onFullScanResult(ScanResult fullScanResult)1383         void onFullScanResult(ScanResult fullScanResult);
onScanStatus()1384         void onScanStatus();
onScanPaused(WifiScanner.ScanData[] data)1385         void onScanPaused(WifiScanner.ScanData[] data);
onScanRestarted()1386         void onScanRestarted();
1387     }
1388 
onScanResultsAvailable(int id)1389     synchronized static void onScanResultsAvailable(int id) {
1390         if (sScanEventHandler  != null) {
1391             sScanEventHandler.onScanResultsAvailable();
1392         }
1393     }
1394 
1395     /* scan status, keep these values in sync with gscan.h */
1396     private static int WIFI_SCAN_BUFFER_FULL = 0;
1397     private static int WIFI_SCAN_COMPLETE = 1;
1398 
onScanStatus(int status)1399     synchronized static void onScanStatus(int status) {
1400         if (status == WIFI_SCAN_BUFFER_FULL) {
1401             /* we have a separate event to take care of this */
1402         } else if (status == WIFI_SCAN_COMPLETE) {
1403             if (sScanEventHandler  != null) {
1404                 sScanEventHandler.onScanStatus();
1405             }
1406         }
1407     }
1408 
createWifiSsid(byte[] rawSsid)1409     public static  WifiSsid createWifiSsid (byte[] rawSsid) {
1410         String ssidHexString = String.valueOf(HexEncoding.encode(rawSsid));
1411 
1412         if (ssidHexString == null) {
1413             return null;
1414         }
1415 
1416         WifiSsid wifiSsid = WifiSsid.createFromHex(ssidHexString);
1417 
1418         return wifiSsid;
1419     }
1420 
ssidConvert(byte[] rawSsid)1421     public static String ssidConvert(byte[] rawSsid) {
1422         String ssid;
1423 
1424         CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
1425         try {
1426             CharBuffer decoded = decoder.decode(ByteBuffer.wrap(rawSsid));
1427             ssid = decoded.toString();
1428         } catch (CharacterCodingException cce) {
1429             ssid = null;
1430         }
1431 
1432         if (ssid == null) {
1433             ssid = new String(rawSsid, StandardCharsets.ISO_8859_1);
1434         }
1435 
1436         return ssid;
1437     }
1438 
setSsid(byte[] rawSsid, ScanResult result)1439     public static boolean setSsid(byte[] rawSsid, ScanResult result) {
1440         if (rawSsid == null || rawSsid.length == 0 || result == null) {
1441             return false;
1442         }
1443 
1444         result.SSID = ssidConvert(rawSsid);
1445         result.wifiSsid = createWifiSsid(rawSsid);
1446         return true;
1447     }
1448 
populateScanResult(ScanResult result, byte bytes[], String dbg)1449     static void populateScanResult(ScanResult result, byte bytes[], String dbg) {
1450         int num = 0;
1451         if (bytes == null) return;
1452         if (dbg == null) dbg = "";
1453         for (int i = 0; i < bytes.length - 1; ) {
1454             int type  = bytes[i] & 0xFF;
1455             int len = bytes[i + 1] & 0xFF;
1456             if (i + len + 2 > bytes.length) {
1457                 Log.w(TAG, dbg + "bad length " + len + " of IE " + type + " from " + result.BSSID);
1458                 Log.w(TAG, dbg + "ignoring the rest of the IEs");
1459                 break;
1460             }
1461             num++;
1462             if (DBG) Log.i(TAG, dbg + "bytes[" + i + "] = [" + type + ", " + len + "]" + ", " +
1463                     "next = " + (i + len + 2));
1464             i += len + 2;
1465         }
1466 
1467         int secondChanelOffset = 0;
1468         byte channelMode = 0;
1469         byte centerFreqIndex1 = 0;
1470         byte centerFreqIndex2 = 0;
1471 
1472         boolean is80211McRTTResponder = false;
1473 
1474         ScanResult.InformationElement elements[] = new ScanResult.InformationElement[num];
1475         for (int i = 0, index = 0; i < num; i++) {
1476             int type  = bytes[index] & 0xFF;
1477             int len = bytes[index + 1] & 0xFF;
1478             if (DBG) Log.i(TAG, dbg + "index = " + index + ", type = " + type + ", len = " + len);
1479             ScanResult.InformationElement elem = new ScanResult.InformationElement();
1480             elem.id = type;
1481             elem.bytes = new byte[len];
1482             for (int j = 0; j < len; j++) {
1483                 elem.bytes[j] = bytes[index + j + 2];
1484             }
1485             elements[i] = elem;
1486             int inforStart = index + 2;
1487             index += (len + 2);
1488 
1489             if(type == EID_HT_OPERATION) {
1490                 secondChanelOffset = bytes[inforStart + 1] & 0x3;
1491             } else if(type == EID_VHT_OPERATION) {
1492                 channelMode = bytes[inforStart];
1493                 centerFreqIndex1 = bytes[inforStart + 1];
1494                 centerFreqIndex2 = bytes[inforStart + 2];
1495             } else if (type == EID_EXTENDED_CAPS) {
1496                 int tempIndex = RTT_RESP_ENABLE_BIT / 8;
1497                 byte offset = RTT_RESP_ENABLE_BIT % 8;
1498 
1499                 if(len < tempIndex + 1) {
1500                     is80211McRTTResponder = false;
1501                 } else {
1502                     if ((bytes[inforStart + tempIndex] & ((byte)0x1 << offset)) != 0) {
1503                         is80211McRTTResponder = true;
1504                     } else {
1505                         is80211McRTTResponder = false;
1506                     }
1507                 }
1508             }
1509         }
1510 
1511         if (is80211McRTTResponder) {
1512             result.setFlag(ScanResult.FLAG_80211mc_RESPONDER);
1513         } else {
1514             result.clearFlag(ScanResult.FLAG_80211mc_RESPONDER);
1515         }
1516 
1517         //handle RTT related information
1518         if (channelMode != 0) {
1519             // 80 or 160 MHz
1520             result.channelWidth = channelMode + 1;
1521 
1522             //convert channel index to frequency in MHz, channel 36 is 5180MHz
1523             result.centerFreq0 = (centerFreqIndex1 - 36) * 5 + 5180;
1524 
1525             if(channelMode > 1) { //160MHz
1526                 result.centerFreq1 = (centerFreqIndex2 - 36) * 5 + 5180;
1527             } else {
1528                 result.centerFreq1 = 0;
1529             }
1530         } else {
1531             //20 or 40 MHz
1532             if (secondChanelOffset != 0) {//40MHz
1533                 result.channelWidth = 1;
1534                 if (secondChanelOffset == 1) {
1535                     result.centerFreq0 = result.frequency + 20;
1536                 } else if (secondChanelOffset == 3) {
1537                     result.centerFreq0 = result.frequency - 20;
1538                 } else {
1539                     result.centerFreq0 = 0;
1540                     Log.e(TAG, dbg + ": Error on secondChanelOffset");
1541                 }
1542             } else {
1543                 result.centerFreq0  = 0;
1544                 result.centerFreq1  = 0;
1545             }
1546             result.centerFreq1  = 0;
1547         }
1548         if(DBG) {
1549             Log.d(TAG, dbg + "SSID: " + result.SSID + " ChannelWidth is: " + result.channelWidth +
1550                     " PrimaryFreq: " + result.frequency +" mCenterfreq0: " + result.centerFreq0 +
1551                     " mCenterfreq1: " + result.centerFreq1 + (is80211McRTTResponder ?
1552                     "Support RTT reponder: " : "Do not support RTT responder"));
1553         }
1554 
1555         result.informationElements = elements;
1556     }
1557 
onFullScanResult(int id, ScanResult result, byte bytes[])1558     synchronized static void onFullScanResult(int id, ScanResult result, byte bytes[]) {
1559         if (DBG) Log.i(TAG, "Got a full scan results event, ssid = " + result.SSID + ", " +
1560                 "num = " + bytes.length);
1561 
1562         if (sScanEventHandler == null) {
1563             return;
1564         }
1565         populateScanResult(result, bytes, " onFullScanResult ");
1566 
1567         sScanEventHandler.onFullScanResult(result);
1568     }
1569 
1570     private static int sScanCmdId = 0;
1571     private static ScanEventHandler sScanEventHandler;
1572     private static ScanSettings sScanSettings;
1573 
startScan( ScanSettings settings, ScanEventHandler eventHandler)1574     synchronized public static boolean startScan(
1575             ScanSettings settings, ScanEventHandler eventHandler) {
1576         synchronized (mLock) {
1577             if (isHalStarted()) {
1578 
1579                 if (sScanCmdId != 0) {
1580                     stopScan();
1581                 } else if (sScanSettings != null || sScanEventHandler != null) {
1582                 /* current scan is paused; no need to stop it */
1583                 }
1584 
1585                 sScanCmdId = getNewCmdIdLocked();
1586 
1587                 sScanSettings = settings;
1588                 sScanEventHandler = eventHandler;
1589 
1590                 if (startScanNative(sWlan0Index, sScanCmdId, settings) == false) {
1591                     sScanEventHandler = null;
1592                     sScanSettings = null;
1593                     sScanCmdId = 0;
1594                     return false;
1595                 }
1596 
1597                 return true;
1598             } else {
1599                 return false;
1600             }
1601         }
1602     }
1603 
stopScan()1604     synchronized public static void stopScan() {
1605         synchronized (mLock) {
1606             if (isHalStarted()) {
1607                 stopScanNative(sWlan0Index, sScanCmdId);
1608                 sScanSettings = null;
1609                 sScanEventHandler = null;
1610                 sScanCmdId = 0;
1611             }
1612         }
1613     }
1614 
pauseScan()1615     synchronized public static void pauseScan() {
1616         synchronized (mLock) {
1617             if (isHalStarted()) {
1618                 if (sScanCmdId != 0 && sScanSettings != null && sScanEventHandler != null) {
1619                     Log.d(TAG, "Pausing scan");
1620                     WifiScanner.ScanData scanData[] = getScanResultsNative(sWlan0Index, true);
1621                     stopScanNative(sWlan0Index, sScanCmdId);
1622                     sScanCmdId = 0;
1623                     sScanEventHandler.onScanPaused(scanData);
1624                 }
1625             }
1626         }
1627     }
1628 
restartScan()1629     synchronized public static void restartScan() {
1630         synchronized (mLock) {
1631             if (isHalStarted()) {
1632                 if (sScanCmdId == 0 && sScanSettings != null && sScanEventHandler != null) {
1633                     Log.d(TAG, "Restarting scan");
1634                     ScanEventHandler handler = sScanEventHandler;
1635                     ScanSettings settings = sScanSettings;
1636                     if (startScan(sScanSettings, sScanEventHandler)) {
1637                         sScanEventHandler.onScanRestarted();
1638                     } else {
1639                     /* we are still paused; don't change state */
1640                         sScanEventHandler = handler;
1641                         sScanSettings = settings;
1642                     }
1643                 }
1644             }
1645         }
1646     }
1647 
getScanResults(boolean flush)1648     synchronized public static WifiScanner.ScanData[] getScanResults(boolean flush) {
1649         synchronized (mLock) {
1650             if (isHalStarted()) {
1651                 return getScanResultsNative(sWlan0Index, flush);
1652             } else {
1653                 return null;
1654             }
1655         }
1656     }
1657 
1658     public static interface HotlistEventHandler {
onHotlistApFound(ScanResult[] result)1659         void onHotlistApFound (ScanResult[] result);
onHotlistApLost(ScanResult[] result)1660         void onHotlistApLost  (ScanResult[] result);
1661     }
1662 
1663     private static int sHotlistCmdId = 0;
1664     private static HotlistEventHandler sHotlistEventHandler;
1665 
setHotlistNative(int iface, int id, WifiScanner.HotlistSettings settings)1666     private native static boolean setHotlistNative(int iface, int id,
1667             WifiScanner.HotlistSettings settings);
resetHotlistNative(int iface, int id)1668     private native static boolean resetHotlistNative(int iface, int id);
1669 
setHotlist(WifiScanner.HotlistSettings settings, HotlistEventHandler eventHandler)1670     synchronized public static boolean setHotlist(WifiScanner.HotlistSettings settings,
1671                                     HotlistEventHandler eventHandler) {
1672         synchronized (mLock) {
1673             if (isHalStarted()) {
1674                 if (sHotlistCmdId != 0) {
1675                     return false;
1676                 } else {
1677                     sHotlistCmdId = getNewCmdIdLocked();
1678                 }
1679 
1680                 sHotlistEventHandler = eventHandler;
1681                 if (setHotlistNative(sWlan0Index, sHotlistCmdId, settings) == false) {
1682                     sHotlistEventHandler = null;
1683                     return false;
1684                 }
1685 
1686                 return true;
1687             } else {
1688                 return false;
1689             }
1690         }
1691     }
1692 
resetHotlist()1693     synchronized public static void resetHotlist() {
1694         synchronized (mLock) {
1695             if (isHalStarted()) {
1696                 if (sHotlistCmdId != 0) {
1697                     resetHotlistNative(sWlan0Index, sHotlistCmdId);
1698                     sHotlistCmdId = 0;
1699                     sHotlistEventHandler = null;
1700                 }
1701             }
1702         }
1703     }
1704 
onHotlistApFound(int id, ScanResult[] results)1705     synchronized public static void onHotlistApFound(int id, ScanResult[] results) {
1706         synchronized (mLock) {
1707             if (isHalStarted()) {
1708                 if (sHotlistCmdId != 0) {
1709                     sHotlistEventHandler.onHotlistApFound(results);
1710                 } else {
1711                 /* this can happen because of race conditions */
1712                     Log.d(TAG, "Ignoring hotlist AP found event");
1713                 }
1714             }
1715         }
1716     }
1717 
onHotlistApLost(int id, ScanResult[] results)1718     synchronized public static void onHotlistApLost(int id, ScanResult[] results) {
1719         synchronized (mLock) {
1720             if (isHalStarted()) {
1721                 if (sHotlistCmdId != 0) {
1722                     sHotlistEventHandler.onHotlistApLost(results);
1723                 } else {
1724                 /* this can happen because of race conditions */
1725                     Log.d(TAG, "Ignoring hotlist AP lost event");
1726                 }
1727             }
1728         }
1729     }
1730 
1731     public static interface SignificantWifiChangeEventHandler {
onChangesFound(ScanResult[] result)1732         void onChangesFound(ScanResult[] result);
1733     }
1734 
1735     private static SignificantWifiChangeEventHandler sSignificantWifiChangeHandler;
1736     private static int sSignificantWifiChangeCmdId;
1737 
trackSignificantWifiChangeNative( int iface, int id, WifiScanner.WifiChangeSettings settings)1738     private static native boolean trackSignificantWifiChangeNative(
1739             int iface, int id, WifiScanner.WifiChangeSettings settings);
untrackSignificantWifiChangeNative(int iface, int id)1740     private static native boolean untrackSignificantWifiChangeNative(int iface, int id);
1741 
trackSignificantWifiChange( WifiScanner.WifiChangeSettings settings, SignificantWifiChangeEventHandler handler)1742     synchronized public static boolean trackSignificantWifiChange(
1743             WifiScanner.WifiChangeSettings settings, SignificantWifiChangeEventHandler handler) {
1744         synchronized (mLock) {
1745             if (isHalStarted()) {
1746                 if (sSignificantWifiChangeCmdId != 0) {
1747                     return false;
1748                 } else {
1749                     sSignificantWifiChangeCmdId = getNewCmdIdLocked();
1750                 }
1751 
1752                 sSignificantWifiChangeHandler = handler;
1753                 if (trackSignificantWifiChangeNative(sWlan0Index, sScanCmdId, settings) == false) {
1754                     sSignificantWifiChangeHandler = null;
1755                     return false;
1756                 }
1757 
1758                 return true;
1759             } else {
1760                 return false;
1761             }
1762 
1763         }
1764     }
1765 
untrackSignificantWifiChange()1766     synchronized static void untrackSignificantWifiChange() {
1767         synchronized (mLock) {
1768             if (isHalStarted()) {
1769                 if (sSignificantWifiChangeCmdId != 0) {
1770                     untrackSignificantWifiChangeNative(sWlan0Index, sSignificantWifiChangeCmdId);
1771                     sSignificantWifiChangeCmdId = 0;
1772                     sSignificantWifiChangeHandler = null;
1773                 }
1774             }
1775         }
1776     }
1777 
onSignificantWifiChange(int id, ScanResult[] results)1778     synchronized static void onSignificantWifiChange(int id, ScanResult[] results) {
1779         synchronized (mLock) {
1780             if (sSignificantWifiChangeCmdId != 0) {
1781                 sSignificantWifiChangeHandler.onChangesFound(results);
1782             } else {
1783             /* this can happen because of race conditions */
1784                 Log.d(TAG, "Ignoring significant wifi change");
1785             }
1786         }
1787     }
1788 
getWifiLinkLayerStats(String iface)1789     synchronized public static WifiLinkLayerStats getWifiLinkLayerStats(String iface) {
1790         // TODO: use correct iface name to Index translation
1791         if (iface == null) return null;
1792         synchronized (mLock) {
1793             if (isHalStarted()) {
1794                 return getWifiLinkLayerStatsNative(sWlan0Index);
1795             } else {
1796                 return null;
1797             }
1798         }
1799     }
1800 
setWifiLinkLayerStats(String iface, int enable)1801     synchronized public static void setWifiLinkLayerStats(String iface, int enable) {
1802         if (iface == null) return;
1803         synchronized (mLock) {
1804             if (isHalStarted()) {
1805                 setWifiLinkLayerStatsNative(sWlan0Index, enable);
1806             }
1807         }
1808     }
1809 
getSupportedFeatureSetNative(int iface)1810     public static native int getSupportedFeatureSetNative(int iface);
getSupportedFeatureSet()1811     synchronized public static int getSupportedFeatureSet() {
1812         synchronized (mLock) {
1813             if (isHalStarted()) {
1814                 return getSupportedFeatureSetNative(sWlan0Index);
1815             } else {
1816                 Log.d(TAG, "Failing getSupportedFeatureset because HAL isn't started");
1817                 return 0;
1818             }
1819         }
1820     }
1821 
1822     /* Rtt related commands/events */
1823     public static interface RttEventHandler {
onRttResults(RttManager.RttResult[] result)1824         void onRttResults(RttManager.RttResult[] result);
1825     }
1826 
1827     private static RttEventHandler sRttEventHandler;
1828     private static int sRttCmdId;
1829 
onRttResults(int id, RttManager.RttResult[] results)1830     synchronized private static void onRttResults(int id, RttManager.RttResult[] results) {
1831         if (id == sRttCmdId) {
1832             Log.d(TAG, "Received " + results.length + " rtt results");
1833             sRttEventHandler.onRttResults(results);
1834             sRttCmdId = 0;
1835         } else {
1836             Log.d(TAG, "RTT Received event for unknown cmd = " + id + ", current id = " + sRttCmdId);
1837         }
1838     }
1839 
requestRangeNative( int iface, int id, RttManager.RttParams[] params)1840     private static native boolean requestRangeNative(
1841             int iface, int id, RttManager.RttParams[] params);
cancelRangeRequestNative( int iface, int id, RttManager.RttParams[] params)1842     private static native boolean cancelRangeRequestNative(
1843             int iface, int id, RttManager.RttParams[] params);
1844 
requestRtt( RttManager.RttParams[] params, RttEventHandler handler)1845     synchronized public static boolean requestRtt(
1846             RttManager.RttParams[] params, RttEventHandler handler) {
1847         synchronized (mLock) {
1848             if (isHalStarted()) {
1849                 if (sRttCmdId != 0) {
1850                     Log.v("TAG", "Last one is still under measurement!");
1851                     return false;
1852                 } else {
1853                     sRttCmdId = getNewCmdIdLocked();
1854                 }
1855                 sRttEventHandler = handler;
1856                 Log.v(TAG, "native issue RTT request");
1857                 return requestRangeNative(sWlan0Index, sRttCmdId, params);
1858             } else {
1859                 return false;
1860             }
1861         }
1862     }
1863 
cancelRtt(RttManager.RttParams[] params)1864     synchronized public static boolean cancelRtt(RttManager.RttParams[] params) {
1865         synchronized(mLock) {
1866             if (isHalStarted()) {
1867                 if (sRttCmdId == 0) {
1868                     return false;
1869                 }
1870 
1871                 sRttCmdId = 0;
1872 
1873                 if (cancelRangeRequestNative(sWlan0Index, sRttCmdId, params)) {
1874                     sRttEventHandler = null;
1875                     Log.v(TAG, "RTT cancel Request Successfully");
1876                     return true;
1877                 } else {
1878                     Log.e(TAG, "RTT cancel Request failed");
1879                     return false;
1880                 }
1881             } else {
1882                 return false;
1883             }
1884         }
1885     }
1886 
setScanningMacOuiNative(int iface, byte[] oui)1887     private static native boolean setScanningMacOuiNative(int iface, byte[] oui);
1888 
setScanningMacOui(byte[] oui)1889     synchronized public static boolean setScanningMacOui(byte[] oui) {
1890         synchronized (mLock) {
1891             if (isHalStarted()) {
1892                 return setScanningMacOuiNative(sWlan0Index, oui);
1893             } else {
1894                 return false;
1895             }
1896         }
1897     }
1898 
getChannelsForBandNative( int iface, int band)1899     private static native int[] getChannelsForBandNative(
1900             int iface, int band);
1901 
getChannelsForBand(int band)1902     synchronized public static int [] getChannelsForBand(int band) {
1903         synchronized (mLock) {
1904             if (isHalStarted()) {
1905                 return getChannelsForBandNative(sWlan0Index, band);
1906 	    } else {
1907                 return null;
1908             }
1909         }
1910     }
1911 
isGetChannelsForBandSupportedNative()1912     private static native boolean isGetChannelsForBandSupportedNative();
isGetChannelsForBandSupported()1913     synchronized public static boolean isGetChannelsForBandSupported(){
1914         synchronized (mLock) {
1915             if (isHalStarted()) {
1916                 return isGetChannelsForBandSupportedNative();
1917 	    } else {
1918                 return false;
1919             }
1920         }
1921     }
1922 
setDfsFlagNative(int iface, boolean dfsOn)1923     private static native boolean setDfsFlagNative(int iface, boolean dfsOn);
setDfsFlag(boolean dfsOn)1924     synchronized public static boolean setDfsFlag(boolean dfsOn) {
1925         synchronized (mLock) {
1926             if (isHalStarted()) {
1927                 return setDfsFlagNative(sWlan0Index, dfsOn);
1928             } else {
1929                 return false;
1930             }
1931         }
1932     }
1933 
toggleInterfaceNative(int on)1934     private static native boolean toggleInterfaceNative(int on);
toggleInterface(int on)1935     synchronized public static boolean toggleInterface(int on) {
1936         synchronized (mLock) {
1937             if (isHalStarted()) {
1938                 return toggleInterfaceNative(0);
1939             } else {
1940                 return false;
1941             }
1942         }
1943     }
1944 
getRttCapabilitiesNative(int iface)1945     private static native RttManager.RttCapabilities getRttCapabilitiesNative(int iface);
getRttCapabilities()1946     synchronized public static RttManager.RttCapabilities getRttCapabilities() {
1947         synchronized (mLock) {
1948             if (isHalStarted()) {
1949                 return getRttCapabilitiesNative(sWlan0Index);
1950             }else {
1951                 return null;
1952             }
1953         }
1954     }
1955 
setCountryCodeHalNative(int iface, String CountryCode)1956     private static native boolean setCountryCodeHalNative(int iface, String CountryCode);
setCountryCodeHal( String CountryCode)1957     synchronized public static boolean setCountryCodeHal( String CountryCode) {
1958         synchronized (mLock) {
1959             if (isHalStarted()) {
1960                 return setCountryCodeHalNative(sWlan0Index, CountryCode);
1961             } else {
1962                 return false;
1963             }
1964         }
1965     }
1966 
1967     /* Rtt related commands/events */
1968     public abstract class TdlsEventHandler {
onTdlsStatus(String macAddr, int status, int reason)1969         abstract public void onTdlsStatus(String macAddr, int status, int reason);
1970     }
1971 
1972     private static TdlsEventHandler sTdlsEventHandler;
1973 
enableDisableTdlsNative(int iface, boolean enable, String macAddr)1974     private static native boolean enableDisableTdlsNative(int iface, boolean enable,
1975             String macAddr);
enableDisableTdls(boolean enable, String macAdd, TdlsEventHandler tdlsCallBack)1976     synchronized public static boolean enableDisableTdls(boolean enable, String macAdd,
1977             TdlsEventHandler tdlsCallBack) {
1978         synchronized (mLock) {
1979             sTdlsEventHandler = tdlsCallBack;
1980             return enableDisableTdlsNative(sWlan0Index, enable, macAdd);
1981         }
1982     }
1983 
1984     // Once TDLS per mac and event feature is implemented, this class definition should be
1985     // moved to the right place, like WifiManager etc
1986     public static class TdlsStatus {
1987         int channel;
1988         int global_operating_class;
1989         int state;
1990         int reason;
1991     }
getTdlsStatusNative(int iface, String macAddr)1992     private static native TdlsStatus getTdlsStatusNative(int iface, String macAddr);
getTdlsStatus(String macAdd)1993     synchronized public static TdlsStatus getTdlsStatus (String macAdd) {
1994         synchronized (mLock) {
1995             if (isHalStarted()) {
1996                 return getTdlsStatusNative(sWlan0Index, macAdd);
1997             } else {
1998                 return null;
1999             }
2000         }
2001     }
2002 
2003     //ToFix: Once TDLS per mac and event feature is implemented, this class definition should be
2004     // moved to the right place, like WifiStateMachine etc
2005     public static class TdlsCapabilities {
2006         /* Maximum TDLS session number can be supported by the Firmware and hardware */
2007         int maxConcurrentTdlsSessionNumber;
2008         boolean isGlobalTdlsSupported;
2009         boolean isPerMacTdlsSupported;
2010         boolean isOffChannelTdlsSupported;
2011     }
2012 
2013 
2014 
getTdlsCapabilitiesNative(int iface)2015     private static native TdlsCapabilities getTdlsCapabilitiesNative(int iface);
getTdlsCapabilities()2016     synchronized public static TdlsCapabilities getTdlsCapabilities () {
2017         synchronized (mLock) {
2018             if (isHalStarted()) {
2019                 return getTdlsCapabilitiesNative(sWlan0Index);
2020             } else {
2021                 return null;
2022             }
2023         }
2024     }
2025 
onTdlsStatus(String macAddr, int status, int reason)2026     synchronized private static boolean onTdlsStatus(String macAddr, int status, int reason) {
2027          if (sTdlsEventHandler == null) {
2028              return false;
2029          } else {
2030              sTdlsEventHandler.onTdlsStatus(macAddr, status, reason);
2031              return true;
2032          }
2033     }
2034 
2035     //---------------------------------------------------------------------------------
2036 
2037     /* Wifi Logger commands/events */
2038 
startLogging(int iface)2039     public static native boolean startLogging(int iface);
2040 
2041     public static interface WifiLoggerEventHandler {
onRingBufferData(RingBufferStatus status, byte[] buffer)2042         void onRingBufferData(RingBufferStatus status, byte[] buffer);
onWifiAlert(int errorCode, byte[] buffer)2043         void onWifiAlert(int errorCode, byte[] buffer);
2044     }
2045 
2046     private static WifiLoggerEventHandler sWifiLoggerEventHandler = null;
2047 
onRingBufferData(RingBufferStatus status, byte[] buffer)2048     private static void onRingBufferData(RingBufferStatus status, byte[] buffer) {
2049         if (sWifiLoggerEventHandler != null)
2050             sWifiLoggerEventHandler.onRingBufferData(status, buffer);
2051     }
2052 
onWifiAlert(byte[] buffer, int errorCode)2053     private static void onWifiAlert(byte[] buffer, int errorCode) {
2054         if (sWifiLoggerEventHandler != null)
2055             sWifiLoggerEventHandler.onWifiAlert(errorCode, buffer);
2056     }
2057 
2058     private static int sLogCmdId = -1;
setLoggingEventHandlerNative(int iface, int id)2059     private static native boolean setLoggingEventHandlerNative(int iface, int id);
setLoggingEventHandler(WifiLoggerEventHandler handler)2060     synchronized public static boolean setLoggingEventHandler(WifiLoggerEventHandler handler) {
2061         synchronized (mLock) {
2062             if (isHalStarted()) {
2063                 int oldId =  sLogCmdId;
2064                 sLogCmdId = getNewCmdIdLocked();
2065                 if (!setLoggingEventHandlerNative(sWlan0Index, sLogCmdId)) {
2066                     sLogCmdId = oldId;
2067                     return false;
2068                 }
2069                 sWifiLoggerEventHandler = handler;
2070                 return true;
2071             } else {
2072                 return false;
2073             }
2074         }
2075     }
2076 
startLoggingRingBufferNative(int iface, int verboseLevel, int flags, int minIntervalSec ,int minDataSize, String ringName)2077     private static native boolean startLoggingRingBufferNative(int iface, int verboseLevel,
2078             int flags, int minIntervalSec ,int minDataSize, String ringName);
startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval, int minDataSize, String ringName)2079     synchronized public static boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval,
2080             int minDataSize, String ringName){
2081         synchronized (mLock) {
2082             if (isHalStarted()) {
2083                 return startLoggingRingBufferNative(sWlan0Index, verboseLevel, flags, maxInterval,
2084                         minDataSize, ringName);
2085             } else {
2086                 return false;
2087             }
2088         }
2089     }
2090 
getSupportedLoggerFeatureSetNative(int iface)2091     private static native int getSupportedLoggerFeatureSetNative(int iface);
getSupportedLoggerFeatureSet()2092     synchronized public static int getSupportedLoggerFeatureSet() {
2093         synchronized (mLock) {
2094             if (isHalStarted()) {
2095                 return getSupportedLoggerFeatureSetNative(sWlan0Index);
2096             } else {
2097                 return 0;
2098             }
2099         }
2100     }
2101 
resetLogHandlerNative(int iface, int id)2102     private static native boolean resetLogHandlerNative(int iface, int id);
resetLogHandler()2103     synchronized public static boolean resetLogHandler() {
2104         synchronized (mLock) {
2105             if (isHalStarted()) {
2106                 if (sLogCmdId == -1) {
2107                     Log.e(TAG,"Can not reset handler Before set any handler");
2108                     return false;
2109                 }
2110                 sWifiLoggerEventHandler = null;
2111                 if (resetLogHandlerNative(sWlan0Index, sLogCmdId)) {
2112                     sLogCmdId = -1;
2113                     return true;
2114                 } else {
2115                     return false;
2116                 }
2117             } else {
2118                 return false;
2119             }
2120         }
2121     }
2122 
getDriverVersionNative(int iface)2123     private static native String getDriverVersionNative(int iface);
getDriverVersion()2124     synchronized public static String getDriverVersion() {
2125         synchronized (mLock) {
2126             if (isHalStarted()) {
2127                 return getDriverVersionNative(sWlan0Index);
2128             } else {
2129                 return "";
2130             }
2131         }
2132     }
2133 
2134 
getFirmwareVersionNative(int iface)2135     private static native String getFirmwareVersionNative(int iface);
getFirmwareVersion()2136     synchronized public static String getFirmwareVersion() {
2137         synchronized (mLock) {
2138             if (isHalStarted()) {
2139                 return getFirmwareVersionNative(sWlan0Index);
2140             } else {
2141                 return "";
2142             }
2143         }
2144     }
2145 
2146     public static class RingBufferStatus{
2147         String name;
2148         int flag;
2149         int ringBufferId;
2150         int ringBufferByteSize;
2151         int verboseLevel;
2152         int writtenBytes;
2153         int readBytes;
2154         int writtenRecords;
2155 
2156         @Override
toString()2157         public String toString() {
2158             return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId +
2159                     " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel +
2160                     " writtenBytes: " + writtenBytes + " readBytes: " + readBytes +
2161                     " writtenRecords: " + writtenRecords;
2162         }
2163     }
2164 
getRingBufferStatusNative(int iface)2165     private static native RingBufferStatus[] getRingBufferStatusNative(int iface);
getRingBufferStatus()2166     synchronized public static RingBufferStatus[] getRingBufferStatus() {
2167         synchronized (mLock) {
2168             if (isHalStarted()) {
2169                 return getRingBufferStatusNative(sWlan0Index);
2170             } else {
2171                 return null;
2172             }
2173         }
2174     }
2175 
getRingBufferDataNative(int iface, String ringName)2176     private static native boolean getRingBufferDataNative(int iface, String ringName);
getRingBufferData(String ringName)2177     synchronized public static boolean getRingBufferData(String ringName) {
2178         synchronized (mLock) {
2179             if (isHalStarted()) {
2180                 return getRingBufferDataNative(sWlan0Index, ringName);
2181             } else {
2182                 return false;
2183             }
2184         }
2185     }
2186 
2187     static private byte[] mFwMemoryDump;
onWifiFwMemoryAvailable(byte[] buffer)2188     private static void onWifiFwMemoryAvailable(byte[] buffer) {
2189         mFwMemoryDump = buffer;
2190         if (DBG) {
2191             Log.d(TAG, "onWifiFwMemoryAvailable is called and buffer length is: " +
2192                     (buffer == null ? 0 :  buffer.length));
2193         }
2194     }
2195 
getFwMemoryDumpNative(int iface)2196     private static native boolean getFwMemoryDumpNative(int iface);
getFwMemoryDump()2197     synchronized public static byte[] getFwMemoryDump() {
2198         synchronized (mLock) {
2199             if (isHalStarted()) {
2200                 if(getFwMemoryDumpNative(sWlan0Index)) {
2201                     byte[] fwMemoryDump = mFwMemoryDump;
2202                     mFwMemoryDump = null;
2203                     return fwMemoryDump;
2204                 } else {
2205                     return null;
2206                 }
2207             }
2208 
2209             return null;
2210         }
2211     }
2212 
2213     //---------------------------------------------------------------------------------
2214     /* Configure ePNO */
2215 
2216     public class WifiPnoNetwork {
2217         String SSID;
2218         int rssi_threshold;
2219         int flags;
2220         int auth;
2221         String configKey; // kept for reference
2222 
WifiPnoNetwork(WifiConfiguration config, int threshold)2223         WifiPnoNetwork(WifiConfiguration config, int threshold) {
2224             if (config.SSID == null) {
2225                 this.SSID = "";
2226                 this.flags = 1;
2227             } else {
2228                 this.SSID = config.SSID;
2229             }
2230             this.rssi_threshold = threshold;
2231             if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
2232                 auth |= 2;
2233             } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) ||
2234                     config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) {
2235                 auth |= 4;
2236             } else if (config.wepKeys[0] != null) {
2237                 auth |= 1;
2238             } else {
2239                 auth |= 1;
2240             }
2241 //            auth = 0;
2242             flags |= 6; //A and G
2243             configKey = config.configKey();
2244         }
2245 
2246         @Override
toString()2247         public String toString() {
2248             StringBuilder sbuf = new StringBuilder();
2249             sbuf.append(this.SSID);
2250             sbuf.append(" flags=").append(this.flags);
2251             sbuf.append(" rssi=").append(this.rssi_threshold);
2252             sbuf.append(" auth=").append(this.auth);
2253             return sbuf.toString();
2254         }
2255     }
2256 
2257     public static interface WifiPnoEventHandler {
onPnoNetworkFound(ScanResult results[])2258         void onPnoNetworkFound(ScanResult results[]);
2259     }
2260 
2261     private static WifiPnoEventHandler sWifiPnoEventHandler;
2262 
2263     private static int sPnoCmdId = 0;
2264 
setPnoListNative(int iface, int id, WifiPnoNetwork list[])2265     private native static boolean setPnoListNative(int iface, int id, WifiPnoNetwork list[]);
2266 
setPnoList(WifiPnoNetwork list[], WifiPnoEventHandler eventHandler)2267     synchronized public static boolean setPnoList(WifiPnoNetwork list[],
2268                                                   WifiPnoEventHandler eventHandler) {
2269         Log.e(TAG, "setPnoList cmd " + sPnoCmdId);
2270 
2271         synchronized (mLock) {
2272             if (isHalStarted()) {
2273 
2274                 sPnoCmdId = getNewCmdIdLocked();
2275 
2276                 sWifiPnoEventHandler = eventHandler;
2277                 if (setPnoListNative(sWlan0Index, sPnoCmdId, list)) {
2278                     return true;
2279                 }
2280             }
2281 
2282             sWifiPnoEventHandler = null;
2283             return false;
2284         }
2285     }
2286 
onPnoNetworkFound(int id, ScanResult[] results)2287     synchronized public static void onPnoNetworkFound(int id, ScanResult[] results) {
2288 
2289         if (results == null) {
2290             Log.e(TAG, "onPnoNetworkFound null results");
2291             return;
2292 
2293         }
2294         Log.d(TAG, "WifiNative.onPnoNetworkFound result " + results.length);
2295 
2296         //Log.e(TAG, "onPnoNetworkFound length " + results.length);
2297         //return;
2298         for (int i=0; i<results.length; i++) {
2299             Log.e(TAG, "onPnoNetworkFound SSID " + results[i].SSID
2300                     + " " + results[i].level + " " + results[i].frequency);
2301 
2302             populateScanResult(results[i], results[i].bytes, "onPnoNetworkFound ");
2303             results[i].wifiSsid = WifiSsid.createFromAsciiEncoded(results[i].SSID);
2304         }
2305         synchronized (mLock) {
2306             if (sPnoCmdId != 0 && sWifiPnoEventHandler != null) {
2307                 sWifiPnoEventHandler.onPnoNetworkFound(results);
2308             } else {
2309                 /* this can happen because of race conditions */
2310                 Log.d(TAG, "Ignoring Pno Network found event");
2311             }
2312         }
2313     }
2314 
2315     public class WifiLazyRoamParams {
2316         int A_band_boost_threshold;
2317         int A_band_penalty_threshold;
2318         int A_band_boost_factor;
2319         int A_band_penalty_factor;
2320         int A_band_max_boost;
2321         int lazy_roam_hysteresis;
2322         int alert_roam_rssi_trigger;
2323 
WifiLazyRoamParams()2324         WifiLazyRoamParams() {
2325         }
2326 
2327         @Override
toString()2328         public String toString() {
2329             StringBuilder sbuf = new StringBuilder();
2330             sbuf.append(" A_band_boost_threshold=").append(this.A_band_boost_threshold);
2331             sbuf.append(" A_band_penalty_threshold=").append(this.A_band_penalty_threshold);
2332             sbuf.append(" A_band_boost_factor=").append(this.A_band_boost_factor);
2333             sbuf.append(" A_band_penalty_factor=").append(this.A_band_penalty_factor);
2334             sbuf.append(" A_band_max_boost=").append(this.A_band_max_boost);
2335             sbuf.append(" lazy_roam_hysteresis=").append(this.lazy_roam_hysteresis);
2336             sbuf.append(" alert_roam_rssi_trigger=").append(this.alert_roam_rssi_trigger);
2337             return sbuf.toString();
2338         }
2339     }
2340 
setLazyRoamNative(int iface, int id, boolean enabled, WifiLazyRoamParams param)2341     private native static boolean setLazyRoamNative(int iface, int id,
2342                                               boolean enabled, WifiLazyRoamParams param);
2343 
setLazyRoam(boolean enabled, WifiLazyRoamParams params)2344     synchronized public static boolean setLazyRoam(boolean enabled, WifiLazyRoamParams params) {
2345         synchronized (mLock) {
2346             if (isHalStarted()) {
2347                 sPnoCmdId = getNewCmdIdLocked();
2348                 return setLazyRoamNative(sWlan0Index, sPnoCmdId, enabled, params);
2349             } else {
2350                 return false;
2351             }
2352         }
2353     }
2354 
setBssidBlacklistNative(int iface, int id, String list[])2355     private native static boolean setBssidBlacklistNative(int iface, int id,
2356                                               String list[]);
2357 
setBssidBlacklist(String list[])2358     synchronized public static boolean setBssidBlacklist(String list[]) {
2359         int size = 0;
2360         if (list != null) {
2361             size = list.length;
2362         }
2363         Log.e(TAG, "setBssidBlacklist cmd " + sPnoCmdId + " size " + size);
2364 
2365         synchronized (mLock) {
2366             if (isHalStarted()) {
2367                 sPnoCmdId = getNewCmdIdLocked();
2368                 return setBssidBlacklistNative(sWlan0Index, sPnoCmdId, list);
2369             } else {
2370                 return false;
2371             }
2372         }
2373     }
2374 
setSsidWhitelistNative(int iface, int id, String list[])2375     private native static boolean setSsidWhitelistNative(int iface, int id, String list[]);
2376 
setSsidWhitelist(String list[])2377     synchronized public static boolean setSsidWhitelist(String list[]) {
2378         int size = 0;
2379         if (list != null) {
2380             size = list.length;
2381         }
2382         Log.e(TAG, "setSsidWhitelist cmd " + sPnoCmdId + " size " + size);
2383 
2384         synchronized (mLock) {
2385             if (isHalStarted()) {
2386                 sPnoCmdId = getNewCmdIdLocked();
2387 
2388                 return setSsidWhitelistNative(sWlan0Index, sPnoCmdId, list);
2389             } else {
2390                 return false;
2391             }
2392         }
2393     }
2394 }
2395