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