• 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.annotation.Nullable;
20 import android.net.apf.ApfCapabilities;
21 import android.net.wifi.IApInterface;
22 import android.net.wifi.IClientInterface;
23 import android.net.wifi.RttManager;
24 import android.net.wifi.RttManager.ResponderConfig;
25 import android.net.wifi.ScanResult;
26 import android.net.wifi.WifiConfiguration;
27 import android.net.wifi.WifiLinkLayerStats;
28 import android.net.wifi.WifiScanner;
29 import android.net.wifi.WifiWakeReasonAndCounts;
30 import android.os.SystemClock;
31 import android.util.Log;
32 import android.util.Pair;
33 import android.util.SparseArray;
34 
35 import com.android.internal.annotations.Immutable;
36 import com.android.internal.util.HexDump;
37 import com.android.server.connectivity.KeepalivePacketData;
38 import com.android.server.wifi.util.FrameParser;
39 
40 import java.io.PrintWriter;
41 import java.io.StringWriter;
42 import java.nio.ByteBuffer;
43 import java.nio.CharBuffer;
44 import java.nio.charset.CharacterCodingException;
45 import java.nio.charset.CharsetDecoder;
46 import java.nio.charset.StandardCharsets;
47 import java.text.SimpleDateFormat;
48 import java.util.ArrayList;
49 import java.util.Date;
50 import java.util.Map;
51 import java.util.Objects;
52 import java.util.Set;
53 import java.util.TimeZone;
54 
55 
56 /**
57  * Native calls for bring up/shut down of the supplicant daemon and for
58  * sending requests to the supplicant daemon
59  *
60  * {@hide}
61  */
62 public class WifiNative {
63     private final String mTAG;
64     private final String mInterfaceName;
65     private final SupplicantStaIfaceHal mSupplicantStaIfaceHal;
66     private final WifiVendorHal mWifiVendorHal;
67     private final WificondControl mWificondControl;
68 
WifiNative(String interfaceName, WifiVendorHal vendorHal, SupplicantStaIfaceHal staIfaceHal, WificondControl condControl)69     public WifiNative(String interfaceName, WifiVendorHal vendorHal,
70                       SupplicantStaIfaceHal staIfaceHal, WificondControl condControl) {
71         mTAG = "WifiNative-" + interfaceName;
72         mInterfaceName = interfaceName;
73         mWifiVendorHal = vendorHal;
74         mSupplicantStaIfaceHal = staIfaceHal;
75         mWificondControl = condControl;
76     }
77 
getInterfaceName()78     public String getInterfaceName() {
79         return mInterfaceName;
80     }
81 
82     /**
83      * Enable verbose logging for all sub modules.
84      */
enableVerboseLogging(int verbose)85     public void enableVerboseLogging(int verbose) {
86         mWificondControl.enableVerboseLogging(verbose > 0 ? true : false);
87         mSupplicantStaIfaceHal.enableVerboseLogging(verbose > 0);
88         mWifiVendorHal.enableVerboseLogging(verbose > 0);
89     }
90 
91    /********************************************************
92     * Native Initialization/Deinitialization
93     ********************************************************/
94     public static final int SETUP_SUCCESS = 0;
95     public static final int SETUP_FAILURE_HAL = 1;
96     public static final int SETUP_FAILURE_WIFICOND = 2;
97 
98    /**
99     * Setup wifi native for Client mode operations.
100     *
101     * 1. Starts the Wifi HAL and configures it in client/STA mode.
102     * 2. Setup Wificond to operate in client mode and retrieve the handle to use for client
103     * operations.
104     *
105     * @return Pair of <Integer, IClientInterface> to indicate the status and the associated wificond
106     * client interface binder handler (will be null on failure).
107     */
setupForClientMode()108     public Pair<Integer, IClientInterface> setupForClientMode() {
109         if (!startHalIfNecessary(true)) {
110             Log.e(mTAG, "Failed to start HAL for client mode");
111             return Pair.create(SETUP_FAILURE_HAL, null);
112         }
113         IClientInterface iClientInterface = mWificondControl.setupDriverForClientMode();
114         if (iClientInterface == null) {
115             return Pair.create(SETUP_FAILURE_WIFICOND, null);
116         }
117         return Pair.create(SETUP_SUCCESS, iClientInterface);
118     }
119 
120     /**
121      * Setup wifi native for AP mode operations.
122      *
123      * 1. Starts the Wifi HAL and configures it in AP mode.
124      * 2. Setup Wificond to operate in AP mode and retrieve the handle to use for ap operations.
125      *
126      * @return Pair of <Integer, IApInterface> to indicate the status and the associated wificond
127      * AP interface binder handler (will be null on failure).
128      */
setupForSoftApMode()129     public Pair<Integer, IApInterface> setupForSoftApMode() {
130         if (!startHalIfNecessary(false)) {
131             Log.e(mTAG, "Failed to start HAL for AP mode");
132             return Pair.create(SETUP_FAILURE_HAL, null);
133         }
134         IApInterface iApInterface = mWificondControl.setupDriverForSoftApMode();
135         if (iApInterface == null) {
136             return Pair.create(SETUP_FAILURE_WIFICOND, null);
137         }
138         return Pair.create(SETUP_SUCCESS, iApInterface);
139     }
140 
141     /**
142      * Teardown all mode configurations in wifi native.
143      *
144      * 1. Stops the Wifi HAL.
145      * 2. Tears down all the interfaces from Wificond.
146      */
tearDown()147     public void tearDown() {
148         stopHalIfNecessary();
149         if (!mWificondControl.tearDownInterfaces()) {
150             // TODO(b/34859006): Handle failures.
151             Log.e(mTAG, "Failed to teardown interfaces from Wificond");
152         }
153     }
154 
155     /********************************************************
156      * Wificond operations
157      ********************************************************/
158     /**
159      * Result of a signal poll.
160      */
161     public static class SignalPollResult {
162         // RSSI value in dBM.
163         public int currentRssi;
164         //Transmission bit rate in Mbps.
165         public int txBitrate;
166         // Association frequency in MHz.
167         public int associationFrequency;
168     }
169 
170     /**
171      * WiFi interface transimission counters.
172      */
173     public static class TxPacketCounters {
174         // Number of successfully transmitted packets.
175         public int txSucceeded;
176         // Number of tramsmission failures.
177         public int txFailed;
178     }
179 
180     /**
181     * Disable wpa_supplicant via wificond.
182     * @return Returns true on success.
183     */
disableSupplicant()184     public boolean disableSupplicant() {
185         return mWificondControl.disableSupplicant();
186     }
187 
188     /**
189     * Enable wpa_supplicant via wificond.
190     * @return Returns true on success.
191     */
enableSupplicant()192     public boolean enableSupplicant() {
193         return mWificondControl.enableSupplicant();
194     }
195 
196     /**
197     * Request signal polling to wificond.
198     * Returns an SignalPollResult object.
199     * Returns null on failure.
200     */
signalPoll()201     public SignalPollResult signalPoll() {
202         return mWificondControl.signalPoll();
203     }
204 
205     /**
206      * Fetch TX packet counters on current connection from wificond.
207     * Returns an TxPacketCounters object.
208     * Returns null on failure.
209     */
getTxPacketCounters()210     public TxPacketCounters getTxPacketCounters() {
211         return mWificondControl.getTxPacketCounters();
212     }
213 
214     /**
215      * Start a scan using wificond for the given parameters.
216      * @param freqs list of frequencies to scan for, if null scan all supported channels.
217      * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
218      * @return Returns true on success.
219      */
scan(Set<Integer> freqs, Set<String> hiddenNetworkSSIDs)220     public boolean scan(Set<Integer> freqs, Set<String> hiddenNetworkSSIDs) {
221         return mWificondControl.scan(freqs, hiddenNetworkSSIDs);
222     }
223 
224     /**
225      * Fetch the latest scan result from kernel via wificond.
226      * @return Returns an ArrayList of ScanDetail.
227      * Returns an empty ArrayList on failure.
228      */
getScanResults()229     public ArrayList<ScanDetail> getScanResults() {
230         return mWificondControl.getScanResults(WificondControl.SCAN_TYPE_SINGLE_SCAN);
231     }
232 
233     /**
234      * Fetch the latest scan result from kernel via wificond.
235      * @return Returns an ArrayList of ScanDetail.
236      * Returns an empty ArrayList on failure.
237      */
getPnoScanResults()238     public ArrayList<ScanDetail> getPnoScanResults() {
239         return mWificondControl.getScanResults(WificondControl.SCAN_TYPE_PNO_SCAN);
240     }
241 
242     /**
243      * Start PNO scan.
244      * @param pnoSettings Pno scan configuration.
245      * @return true on success.
246      */
startPnoScan(PnoSettings pnoSettings)247     public boolean startPnoScan(PnoSettings pnoSettings) {
248         return mWificondControl.startPnoScan(pnoSettings);
249     }
250 
251     /**
252      * Stop PNO scan.
253      * @return true on success.
254      */
stopPnoScan()255     public boolean stopPnoScan() {
256         return mWificondControl.stopPnoScan();
257     }
258 
259     /********************************************************
260      * Supplicant operations
261      ********************************************************/
262 
263     /**
264      * This method is called repeatedly until the connection to wpa_supplicant is established.
265      *
266      * @return true if connection is established, false otherwise.
267      * TODO: Add unit tests for these once we remove the legacy code.
268      */
connectToSupplicant()269     public boolean connectToSupplicant() {
270         // Start initialization if not already started.
271         if (!mSupplicantStaIfaceHal.isInitializationStarted()
272                 && !mSupplicantStaIfaceHal.initialize()) {
273             return false;
274         }
275         // Check if the initialization is complete.
276         return mSupplicantStaIfaceHal.isInitializationComplete();
277     }
278 
279     /**
280      * Close supplicant connection.
281      */
closeSupplicantConnection()282     public void closeSupplicantConnection() {
283         // Nothing to do for HIDL.
284     }
285 
286     /**
287      * Set supplicant log level
288      *
289      * @param turnOnVerbose Whether to turn on verbose logging or not.
290      */
setSupplicantLogLevel(boolean turnOnVerbose)291     public void setSupplicantLogLevel(boolean turnOnVerbose) {
292         mSupplicantStaIfaceHal.setLogLevel(turnOnVerbose);
293     }
294 
295     /**
296      * Trigger a reconnection if the iface is disconnected.
297      *
298      * @return true if request is sent successfully, false otherwise.
299      */
reconnect()300     public boolean reconnect() {
301         return mSupplicantStaIfaceHal.reconnect();
302     }
303 
304     /**
305      * Trigger a reassociation even if the iface is currently connected.
306      *
307      * @return true if request is sent successfully, false otherwise.
308      */
reassociate()309     public boolean reassociate() {
310         return mSupplicantStaIfaceHal.reassociate();
311     }
312 
313     /**
314      * Trigger a disconnection from the currently connected network.
315      *
316      * @return true if request is sent successfully, false otherwise.
317      */
disconnect()318     public boolean disconnect() {
319         return mSupplicantStaIfaceHal.disconnect();
320     }
321 
322     /**
323      * Makes a callback to HIDL to getMacAddress from supplicant
324      *
325      * @return string containing the MAC address, or null on a failed call
326      */
getMacAddress()327     public String getMacAddress() {
328         return mSupplicantStaIfaceHal.getMacAddress();
329     }
330 
331     public static final int RX_FILTER_TYPE_V4_MULTICAST = 0;
332     public static final int RX_FILTER_TYPE_V6_MULTICAST = 1;
333     /**
334      * Start filtering out Multicast V4 packets
335      * @return {@code true} if the operation succeeded, {@code false} otherwise
336      *
337      * Multicast filtering rules work as follows:
338      *
339      * The driver can filter multicast (v4 and/or v6) and broadcast packets when in
340      * a power optimized mode (typically when screen goes off).
341      *
342      * In order to prevent the driver from filtering the multicast/broadcast packets, we have to
343      * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective
344      *
345      * DRIVER RXFILTER-ADD Num
346      *   where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6
347      *
348      * and DRIVER RXFILTER-START
349      * In order to stop the usage of these rules, we do
350      *
351      * DRIVER RXFILTER-STOP
352      * DRIVER RXFILTER-REMOVE Num
353      *   where Num is as described for RXFILTER-ADD
354      *
355      * The  SETSUSPENDOPT driver command overrides the filtering rules
356      */
startFilteringMulticastV4Packets()357     public boolean startFilteringMulticastV4Packets() {
358         return mSupplicantStaIfaceHal.stopRxFilter()
359                 && mSupplicantStaIfaceHal.removeRxFilter(
360                 RX_FILTER_TYPE_V4_MULTICAST)
361                 && mSupplicantStaIfaceHal.startRxFilter();
362     }
363 
364     /**
365      * Stop filtering out Multicast V4 packets.
366      * @return {@code true} if the operation succeeded, {@code false} otherwise
367      */
stopFilteringMulticastV4Packets()368     public boolean stopFilteringMulticastV4Packets() {
369         return mSupplicantStaIfaceHal.stopRxFilter()
370                 && mSupplicantStaIfaceHal.addRxFilter(
371                 RX_FILTER_TYPE_V4_MULTICAST)
372                 && mSupplicantStaIfaceHal.startRxFilter();
373     }
374 
375     /**
376      * Start filtering out Multicast V6 packets
377      * @return {@code true} if the operation succeeded, {@code false} otherwise
378      */
startFilteringMulticastV6Packets()379     public boolean startFilteringMulticastV6Packets() {
380         return mSupplicantStaIfaceHal.stopRxFilter()
381                 && mSupplicantStaIfaceHal.removeRxFilter(
382                 RX_FILTER_TYPE_V6_MULTICAST)
383                 && mSupplicantStaIfaceHal.startRxFilter();
384     }
385 
386     /**
387      * Stop filtering out Multicast V6 packets.
388      * @return {@code true} if the operation succeeded, {@code false} otherwise
389      */
stopFilteringMulticastV6Packets()390     public boolean stopFilteringMulticastV6Packets() {
391         return mSupplicantStaIfaceHal.stopRxFilter()
392                 && mSupplicantStaIfaceHal.addRxFilter(
393                 RX_FILTER_TYPE_V6_MULTICAST)
394                 && mSupplicantStaIfaceHal.startRxFilter();
395     }
396 
397     public static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED  = 0;
398     public static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1;
399     public static final int BLUETOOTH_COEXISTENCE_MODE_SENSE    = 2;
400     /**
401       * Sets the bluetooth coexistence mode.
402       *
403       * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED},
404       *            {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or
405       *            {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}.
406       * @return Whether the mode was successfully set.
407       */
setBluetoothCoexistenceMode(int mode)408     public boolean setBluetoothCoexistenceMode(int mode) {
409         return mSupplicantStaIfaceHal.setBtCoexistenceMode(mode);
410     }
411 
412     /**
413      * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
414      * some of the low-level scan parameters used by the driver are changed to
415      * reduce interference with A2DP streaming.
416      *
417      * @param setCoexScanMode whether to enable or disable this mode
418      * @return {@code true} if the command succeeded, {@code false} otherwise.
419      */
setBluetoothCoexistenceScanMode(boolean setCoexScanMode)420     public boolean setBluetoothCoexistenceScanMode(boolean setCoexScanMode) {
421         return mSupplicantStaIfaceHal.setBtCoexistenceScanModeEnabled(setCoexScanMode);
422     }
423 
424     /**
425      * Enable or disable suspend mode optimizations.
426      *
427      * @param enabled true to enable, false otherwise.
428      * @return true if request is sent successfully, false otherwise.
429      */
setSuspendOptimizations(boolean enabled)430     public boolean setSuspendOptimizations(boolean enabled) {
431         return mSupplicantStaIfaceHal.setSuspendModeEnabled(enabled);
432     }
433 
434     /**
435      * Set country code.
436      *
437      * @param countryCode 2 byte ASCII string. For ex: US, CA.
438      * @return true if request is sent successfully, false otherwise.
439      */
setCountryCode(String countryCode)440     public boolean setCountryCode(String countryCode) {
441         return mSupplicantStaIfaceHal.setCountryCode(countryCode);
442     }
443 
444     /**
445      * Initiate TDLS discover and setup or teardown with the specified peer.
446      *
447      * @param macAddr MAC Address of the peer.
448      * @param enable true to start discovery and setup, false to teardown.
449      */
startTdls(String macAddr, boolean enable)450     public void startTdls(String macAddr, boolean enable) {
451         if (enable) {
452             mSupplicantStaIfaceHal.initiateTdlsDiscover(macAddr);
453             mSupplicantStaIfaceHal.initiateTdlsSetup(macAddr);
454         } else {
455             mSupplicantStaIfaceHal.initiateTdlsTeardown(macAddr);
456         }
457     }
458 
459     /**
460      * Start WPS pin display operation with the specified peer.
461      *
462      * @param bssid BSSID of the peer.
463      * @return true if request is sent successfully, false otherwise.
464      */
startWpsPbc(String bssid)465     public boolean startWpsPbc(String bssid) {
466         return mSupplicantStaIfaceHal.startWpsPbc(bssid);
467     }
468 
469     /**
470      * Start WPS pin keypad operation with the specified pin.
471      *
472      * @param pin Pin to be used.
473      * @return true if request is sent successfully, false otherwise.
474      */
startWpsPinKeypad(String pin)475     public boolean startWpsPinKeypad(String pin) {
476         return mSupplicantStaIfaceHal.startWpsPinKeypad(pin);
477     }
478 
479     /**
480      * Start WPS pin display operation with the specified peer.
481      *
482      * @param bssid BSSID of the peer.
483      * @return new pin generated on success, null otherwise.
484      */
startWpsPinDisplay(String bssid)485     public String startWpsPinDisplay(String bssid) {
486         return mSupplicantStaIfaceHal.startWpsPinDisplay(bssid);
487     }
488 
489     /**
490      * Sets whether to use external sim for SIM/USIM processing.
491      *
492      * @param external true to enable, false otherwise.
493      * @return true if request is sent successfully, false otherwise.
494      */
setExternalSim(boolean external)495     public boolean setExternalSim(boolean external) {
496         return mSupplicantStaIfaceHal.setExternalSim(external);
497     }
498 
499     /**
500      * Sim auth response types.
501      */
502     public static final String SIM_AUTH_RESP_TYPE_GSM_AUTH = "GSM-AUTH";
503     public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTH = "UMTS-AUTH";
504     public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTS = "UMTS-AUTS";
505 
506     /**
507      * Send the sim auth response for the currently configured network.
508      *
509      * @param type |GSM-AUTH|, |UMTS-AUTH| or |UMTS-AUTS|.
510      * @param response Response params.
511      * @return true if succeeds, false otherwise.
512      */
simAuthResponse(int id, String type, String response)513     public boolean simAuthResponse(int id, String type, String response) {
514         if (SIM_AUTH_RESP_TYPE_GSM_AUTH.equals(type)) {
515             return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthResponse(response);
516         } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTH.equals(type)) {
517             return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthResponse(response);
518         } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTS.equals(type)) {
519             return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAutsResponse(response);
520         } else {
521             return false;
522         }
523     }
524 
525     /**
526      * Send the eap sim gsm auth failure for the currently configured network.
527      *
528      * @return true if succeeds, false otherwise.
529      */
simAuthFailedResponse(int id)530     public boolean simAuthFailedResponse(int id) {
531         return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthFailure();
532     }
533 
534     /**
535      * Send the eap sim umts auth failure for the currently configured network.
536      *
537      * @return true if succeeds, false otherwise.
538      */
umtsAuthFailedResponse(int id)539     public boolean umtsAuthFailedResponse(int id) {
540         return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthFailure();
541     }
542 
543     /**
544      * Send the eap identity response for the currently configured network.
545      *
546      * @param response String to send.
547      * @return true if succeeds, false otherwise.
548      */
simIdentityResponse(int id, String response)549     public boolean simIdentityResponse(int id, String response) {
550         return mSupplicantStaIfaceHal.sendCurrentNetworkEapIdentityResponse(response);
551     }
552 
553     /**
554      * This get anonymous identity from supplicant and returns it as a string.
555      *
556      * @return anonymous identity string if succeeds, null otherwise.
557      */
getEapAnonymousIdentity()558     public String getEapAnonymousIdentity() {
559         return mSupplicantStaIfaceHal.getCurrentNetworkEapAnonymousIdentity();
560     }
561 
562     /**
563      * Start WPS pin registrar operation with the specified peer and pin.
564      *
565      * @param bssid BSSID of the peer.
566      * @param pin Pin to be used.
567      * @return true if request is sent successfully, false otherwise.
568      */
startWpsRegistrar(String bssid, String pin)569     public boolean startWpsRegistrar(String bssid, String pin) {
570         return mSupplicantStaIfaceHal.startWpsRegistrar(bssid, pin);
571     }
572 
573     /**
574      * Cancels any ongoing WPS requests.
575      *
576      * @return true if request is sent successfully, false otherwise.
577      */
cancelWps()578     public boolean cancelWps() {
579         return mSupplicantStaIfaceHal.cancelWps();
580     }
581 
582     /**
583      * Set WPS device name.
584      *
585      * @param name String to be set.
586      * @return true if request is sent successfully, false otherwise.
587      */
setDeviceName(String name)588     public boolean setDeviceName(String name) {
589         return mSupplicantStaIfaceHal.setWpsDeviceName(name);
590     }
591 
592     /**
593      * Set WPS device type.
594      *
595      * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg>
596      * @return true if request is sent successfully, false otherwise.
597      */
setDeviceType(String type)598     public boolean setDeviceType(String type) {
599         return mSupplicantStaIfaceHal.setWpsDeviceType(type);
600     }
601 
602     /**
603      * Set WPS config methods
604      *
605      * @param cfg List of config methods.
606      * @return true if request is sent successfully, false otherwise.
607      */
setConfigMethods(String cfg)608     public boolean setConfigMethods(String cfg) {
609         return mSupplicantStaIfaceHal.setWpsConfigMethods(cfg);
610     }
611 
612     /**
613      * Set WPS manufacturer.
614      *
615      * @param value String to be set.
616      * @return true if request is sent successfully, false otherwise.
617      */
setManufacturer(String value)618     public boolean setManufacturer(String value) {
619         return mSupplicantStaIfaceHal.setWpsManufacturer(value);
620     }
621 
622     /**
623      * Set WPS model name.
624      *
625      * @param value String to be set.
626      * @return true if request is sent successfully, false otherwise.
627      */
setModelName(String value)628     public boolean setModelName(String value) {
629         return mSupplicantStaIfaceHal.setWpsModelName(value);
630     }
631 
632     /**
633      * Set WPS model number.
634      *
635      * @param value String to be set.
636      * @return true if request is sent successfully, false otherwise.
637      */
setModelNumber(String value)638     public boolean setModelNumber(String value) {
639         return mSupplicantStaIfaceHal.setWpsModelNumber(value);
640     }
641 
642     /**
643      * Set WPS serial number.
644      *
645      * @param value String to be set.
646      * @return true if request is sent successfully, false otherwise.
647      */
setSerialNumber(String value)648     public boolean setSerialNumber(String value) {
649         return mSupplicantStaIfaceHal.setWpsSerialNumber(value);
650     }
651 
652     /**
653      * Enable or disable power save mode.
654      *
655      * @param enabled true to enable, false to disable.
656      */
setPowerSave(boolean enabled)657     public void setPowerSave(boolean enabled) {
658         mSupplicantStaIfaceHal.setPowerSave(enabled);
659     }
660 
661     /**
662      * Set concurrency priority between P2P & STA operations.
663      *
664      * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations,
665      *                            false otherwise.
666      * @return true if request is sent successfully, false otherwise.
667      */
setConcurrencyPriority(boolean isStaHigherPriority)668     public boolean setConcurrencyPriority(boolean isStaHigherPriority) {
669         return mSupplicantStaIfaceHal.setConcurrencyPriority(isStaHigherPriority);
670     }
671 
672     /**
673      * Enable/Disable auto reconnect functionality in wpa_supplicant.
674      *
675      * @param enable true to enable auto reconnecting, false to disable.
676      * @return true if request is sent successfully, false otherwise.
677      */
enableStaAutoReconnect(boolean enable)678     public boolean enableStaAutoReconnect(boolean enable) {
679         return mSupplicantStaIfaceHal.enableAutoReconnect(enable);
680     }
681 
682     /**
683      * Migrate all the configured networks from wpa_supplicant.
684      *
685      * @param configs       Map of configuration key to configuration objects corresponding to all
686      *                      the networks.
687      * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf
688      * @return Max priority of all the configs.
689      */
migrateNetworksFromSupplicant(Map<String, WifiConfiguration> configs, SparseArray<Map<String, String>> networkExtras)690     public boolean migrateNetworksFromSupplicant(Map<String, WifiConfiguration> configs,
691                                                  SparseArray<Map<String, String>> networkExtras) {
692         return mSupplicantStaIfaceHal.loadNetworks(configs, networkExtras);
693     }
694 
695     /**
696      * Add the provided network configuration to wpa_supplicant and initiate connection to it.
697      * This method does the following:
698      * 1. Abort any ongoing scan to unblock the connection request.
699      * 2. Remove any existing network in wpa_supplicant(This implicitly triggers disconnect).
700      * 3. Add a new network to wpa_supplicant.
701      * 4. Save the provided configuration to wpa_supplicant.
702      * 5. Select the new network in wpa_supplicant.
703      * 6. Triggers reconnect command to wpa_supplicant.
704      *
705      * @param configuration WifiConfiguration parameters for the provided network.
706      * @return {@code true} if it succeeds, {@code false} otherwise
707      */
connectToNetwork(WifiConfiguration configuration)708     public boolean connectToNetwork(WifiConfiguration configuration) {
709         // Abort ongoing scan before connect() to unblock connection request.
710         mWificondControl.abortScan();
711         return mSupplicantStaIfaceHal.connectToNetwork(configuration);
712     }
713 
714     /**
715      * Initiates roaming to the already configured network in wpa_supplicant. If the network
716      * configuration provided does not match the already configured network, then this triggers
717      * a new connection attempt (instead of roam).
718      * 1. Abort any ongoing scan to unblock the roam request.
719      * 2. First check if we're attempting to connect to the same network as we currently have
720      * configured.
721      * 3. Set the new bssid for the network in wpa_supplicant.
722      * 4. Triggers reassociate command to wpa_supplicant.
723      *
724      * @param configuration WifiConfiguration parameters for the provided network.
725      * @return {@code true} if it succeeds, {@code false} otherwise
726      */
roamToNetwork(WifiConfiguration configuration)727     public boolean roamToNetwork(WifiConfiguration configuration) {
728         // Abort ongoing scan before connect() to unblock roaming request.
729         mWificondControl.abortScan();
730         return mSupplicantStaIfaceHal.roamToNetwork(configuration);
731     }
732 
733     /**
734      * Get the framework network ID corresponding to the provided supplicant network ID for the
735      * network configured in wpa_supplicant.
736      *
737      * @param supplicantNetworkId network ID in wpa_supplicant for the network.
738      * @return Corresponding framework network ID if found, -1 if network not found.
739      */
getFrameworkNetworkId(int supplicantNetworkId)740     public int getFrameworkNetworkId(int supplicantNetworkId) {
741         return supplicantNetworkId;
742     }
743 
744     /**
745      * Remove all the networks.
746      *
747      * @return {@code true} if it succeeds, {@code false} otherwise
748      */
removeAllNetworks()749     public boolean removeAllNetworks() {
750         return mSupplicantStaIfaceHal.removeAllNetworks();
751     }
752 
753     /**
754      * Set the BSSID for the currently configured network in wpa_supplicant.
755      *
756      * @return true if successful, false otherwise.
757      */
setConfiguredNetworkBSSID(String bssid)758     public boolean setConfiguredNetworkBSSID(String bssid) {
759         return mSupplicantStaIfaceHal.setCurrentNetworkBssid(bssid);
760     }
761 
762     /**
763      * Initiate ANQP query.
764      *
765      * @param bssid BSSID of the AP to be queried
766      * @param anqpIds Set of anqp IDs.
767      * @param hs20Subtypes Set of HS20 subtypes.
768      * @return true on success, false otherwise.
769      */
requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes)770     public boolean requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes) {
771         if (bssid == null || ((anqpIds == null || anqpIds.isEmpty())
772                 && (hs20Subtypes == null || hs20Subtypes.isEmpty()))) {
773             Log.e(mTAG, "Invalid arguments for ANQP request.");
774             return false;
775         }
776         ArrayList<Short> anqpIdList = new ArrayList<>();
777         for (Integer anqpId : anqpIds) {
778             anqpIdList.add(anqpId.shortValue());
779         }
780         ArrayList<Integer> hs20SubtypeList = new ArrayList<>();
781         hs20SubtypeList.addAll(hs20Subtypes);
782         return mSupplicantStaIfaceHal.initiateAnqpQuery(bssid, anqpIdList, hs20SubtypeList);
783     }
784 
785     /**
786      * Request a passpoint icon file |filename| from the specified AP |bssid|.
787      * @param bssid BSSID of the AP
788      * @param fileName name of the icon file
789      * @return true if request is sent successfully, false otherwise
790      */
requestIcon(String bssid, String fileName)791     public boolean requestIcon(String  bssid, String fileName) {
792         if (bssid == null || fileName == null) {
793             Log.e(mTAG, "Invalid arguments for Icon request.");
794             return false;
795         }
796         return mSupplicantStaIfaceHal.initiateHs20IconQuery(bssid, fileName);
797     }
798 
799     /**
800      * Get the currently configured network's WPS NFC token.
801      *
802      * @return Hex string corresponding to the WPS NFC token.
803      */
getCurrentNetworkWpsNfcConfigurationToken()804     public String getCurrentNetworkWpsNfcConfigurationToken() {
805         return mSupplicantStaIfaceHal.getCurrentNetworkWpsNfcConfigurationToken();
806     }
807 
808     /** Remove the request |networkId| from supplicant if it's the current network,
809      * if the current configured network matches |networkId|.
810      *
811      * @param networkId network id of the network to be removed from supplicant.
812      */
removeNetworkIfCurrent(int networkId)813     public void removeNetworkIfCurrent(int networkId) {
814         mSupplicantStaIfaceHal.removeNetworkIfCurrent(networkId);
815     }
816 
817     /********************************************************
818      * Vendor HAL operations
819      ********************************************************/
820     /**
821      * Callback to notify vendor HAL death.
822      */
823     public interface VendorHalDeathEventHandler {
824         /**
825          * Invoked when the vendor HAL dies.
826          */
onDeath()827         void onDeath();
828     }
829 
830     /**
831      * Initializes the vendor HAL. This is just used to initialize the {@link HalDeviceManager}.
832      */
initializeVendorHal(VendorHalDeathEventHandler handler)833     public boolean initializeVendorHal(VendorHalDeathEventHandler handler) {
834         return mWifiVendorHal.initialize(handler);
835     }
836 
837     /**
838      * Bring up the Vendor HAL and configure for STA mode or AP mode, if vendor HAL is supported.
839      *
840      * @param isStaMode true to start HAL in STA mode, false to start in AP mode.
841      * @return false if the HAL start fails, true if successful or if vendor HAL not supported.
842      */
startHalIfNecessary(boolean isStaMode)843     private boolean startHalIfNecessary(boolean isStaMode) {
844         if (!mWifiVendorHal.isVendorHalSupported()) {
845             Log.i(mTAG, "Vendor HAL not supported, Ignore start...");
846             return true;
847         }
848         return mWifiVendorHal.startVendorHal(isStaMode);
849     }
850 
851     /**
852      * Stops the HAL, if vendor HAL is supported.
853      */
stopHalIfNecessary()854     private void stopHalIfNecessary() {
855         if (!mWifiVendorHal.isVendorHalSupported()) {
856             Log.i(mTAG, "Vendor HAL not supported, Ignore stop...");
857             return;
858         }
859         mWifiVendorHal.stopVendorHal();
860     }
861 
862     /**
863      * Tests whether the HAL is running or not
864      */
isHalStarted()865     public boolean isHalStarted() {
866         return mWifiVendorHal.isHalStarted();
867     }
868 
869     // TODO: Change variable names to camel style.
870     public static class ScanCapabilities {
871         public int  max_scan_cache_size;
872         public int  max_scan_buckets;
873         public int  max_ap_cache_per_scan;
874         public int  max_rssi_sample_size;
875         public int  max_scan_reporting_threshold;
876     }
877 
878     /**
879      * Gets the scan capabilities
880      *
881      * @param capabilities object to be filled in
882      * @return true for success. false for failure
883      */
getBgScanCapabilities(ScanCapabilities capabilities)884     public boolean getBgScanCapabilities(ScanCapabilities capabilities) {
885         return mWifiVendorHal.getBgScanCapabilities(capabilities);
886     }
887 
888     public static class ChannelSettings {
889         public int frequency;
890         public int dwell_time_ms;
891         public boolean passive;
892     }
893 
894     public static class BucketSettings {
895         public int bucket;
896         public int band;
897         public int period_ms;
898         public int max_period_ms;
899         public int step_count;
900         public int report_events;
901         public int num_channels;
902         public ChannelSettings[] channels;
903     }
904 
905     /**
906      * Network parameters for hidden networks to be scanned for.
907      */
908     public static class HiddenNetwork {
909         public String ssid;
910 
911         @Override
equals(Object otherObj)912         public boolean equals(Object otherObj) {
913             if (this == otherObj) {
914                 return true;
915             } else if (otherObj == null || getClass() != otherObj.getClass()) {
916                 return false;
917             }
918             HiddenNetwork other = (HiddenNetwork) otherObj;
919             return Objects.equals(ssid, other.ssid);
920         }
921 
922         @Override
hashCode()923         public int hashCode() {
924             return (ssid == null ? 0 : ssid.hashCode());
925         }
926     }
927 
928     public static class ScanSettings {
929         public int base_period_ms;
930         public int max_ap_per_scan;
931         public int report_threshold_percent;
932         public int report_threshold_num_scans;
933         public int num_buckets;
934         /* Not used for bg scans. Only works for single scans. */
935         public HiddenNetwork[] hiddenNetworks;
936         public BucketSettings[] buckets;
937     }
938 
939     /**
940      * Network parameters to start PNO scan.
941      */
942     public static class PnoNetwork {
943         public String ssid;
944         public byte flags;
945         public byte auth_bit_field;
946 
947         @Override
equals(Object otherObj)948         public boolean equals(Object otherObj) {
949             if (this == otherObj) {
950                 return true;
951             } else if (otherObj == null || getClass() != otherObj.getClass()) {
952                 return false;
953             }
954             PnoNetwork other = (PnoNetwork) otherObj;
955             return ((Objects.equals(ssid, other.ssid)) && (flags == other.flags)
956                     && (auth_bit_field == other.auth_bit_field));
957         }
958 
959         @Override
hashCode()960         public int hashCode() {
961             int result = (ssid == null ? 0 : ssid.hashCode());
962             result ^= ((int) flags * 31) + ((int) auth_bit_field << 8);
963             return result;
964         }
965     }
966 
967     /**
968      * Parameters to start PNO scan. This holds the list of networks which are going to used for
969      * PNO scan.
970      */
971     public static class PnoSettings {
972         public int min5GHzRssi;
973         public int min24GHzRssi;
974         public int initialScoreMax;
975         public int currentConnectionBonus;
976         public int sameNetworkBonus;
977         public int secureBonus;
978         public int band5GHzBonus;
979         public int periodInMs;
980         public boolean isConnected;
981         public PnoNetwork[] networkList;
982     }
983 
984     public static interface ScanEventHandler {
985         /**
986          * Called for each AP as it is found with the entire contents of the beacon/probe response.
987          * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified.
988          */
onFullScanResult(ScanResult fullScanResult, int bucketsScanned)989         void onFullScanResult(ScanResult fullScanResult, int bucketsScanned);
990         /**
991          * Callback on an event during a gscan scan.
992          * See WifiNative.WIFI_SCAN_* for possible values.
993          */
onScanStatus(int event)994         void onScanStatus(int event);
995         /**
996          * Called with the current cached scan results when gscan is paused.
997          */
onScanPaused(WifiScanner.ScanData[] data)998         void onScanPaused(WifiScanner.ScanData[] data);
999         /**
1000          * Called with the current cached scan results when gscan is resumed.
1001          */
onScanRestarted()1002         void onScanRestarted();
1003     }
1004 
1005     /**
1006      * Handler to notify the occurrence of various events during PNO scan.
1007      */
1008     public interface PnoEventHandler {
1009         /**
1010          * Callback to notify when one of the shortlisted networks is found during PNO scan.
1011          * @param results List of Scan results received.
1012          */
onPnoNetworkFound(ScanResult[] results)1013         void onPnoNetworkFound(ScanResult[] results);
1014 
1015         /**
1016          * Callback to notify when the PNO scan schedule fails.
1017          */
onPnoScanFailed()1018         void onPnoScanFailed();
1019     }
1020 
1021     public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0;
1022     public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1;
1023     public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2;
1024     public static final int WIFI_SCAN_FAILED = 3;
1025 
1026     /**
1027      * Starts a background scan.
1028      * Any ongoing scan will be stopped first
1029      *
1030      * @param settings     to control the scan
1031      * @param eventHandler to call with the results
1032      * @return true for success
1033      */
startBgScan(ScanSettings settings, ScanEventHandler eventHandler)1034     public boolean startBgScan(ScanSettings settings, ScanEventHandler eventHandler) {
1035         return mWifiVendorHal.startBgScan(settings, eventHandler);
1036     }
1037 
1038     /**
1039      * Stops any ongoing backgound scan
1040      */
stopBgScan()1041     public void stopBgScan() {
1042         mWifiVendorHal.stopBgScan();
1043     }
1044 
1045     /**
1046      * Pauses an ongoing backgound scan
1047      */
pauseBgScan()1048     public void pauseBgScan() {
1049         mWifiVendorHal.pauseBgScan();
1050     }
1051 
1052     /**
1053      * Restarts a paused scan
1054      */
restartBgScan()1055     public void restartBgScan() {
1056         mWifiVendorHal.restartBgScan();
1057     }
1058 
1059     /**
1060      * Gets the latest scan results received.
1061      */
getBgScanResults()1062     public WifiScanner.ScanData[] getBgScanResults() {
1063         return mWifiVendorHal.getBgScanResults();
1064     }
1065 
getWifiLinkLayerStats(String iface)1066     public WifiLinkLayerStats getWifiLinkLayerStats(String iface) {
1067         return mWifiVendorHal.getWifiLinkLayerStats();
1068     }
1069 
1070     /**
1071      * Get the supported features
1072      *
1073      * @return bitmask defined by WifiManager.WIFI_FEATURE_*
1074      */
getSupportedFeatureSet()1075     public int getSupportedFeatureSet() {
1076         return mWifiVendorHal.getSupportedFeatureSet();
1077     }
1078 
1079     public static interface RttEventHandler {
onRttResults(RttManager.RttResult[] result)1080         void onRttResults(RttManager.RttResult[] result);
1081     }
1082 
1083     /**
1084      * Starts a new rtt request
1085      *
1086      * @param params RTT request params. Refer to {@link RttManager#RttParams}.
1087      * @param handler Callback to be invoked to notify any results.
1088      * @return true if the request was successful, false otherwise.
1089      */
requestRtt( RttManager.RttParams[] params, RttEventHandler handler)1090     public boolean requestRtt(
1091             RttManager.RttParams[] params, RttEventHandler handler) {
1092         return mWifiVendorHal.requestRtt(params, handler);
1093     }
1094 
1095     /**
1096      * Cancels an outstanding rtt request
1097      *
1098      * @param params RTT request params. Refer to {@link RttManager#RttParams}
1099      * @return true if there was an outstanding request and it was successfully cancelled
1100      */
cancelRtt(RttManager.RttParams[] params)1101     public boolean cancelRtt(RttManager.RttParams[] params) {
1102         return mWifiVendorHal.cancelRtt(params);
1103     }
1104 
1105     /**
1106      * Enable RTT responder role on the device. Returns {@link ResponderConfig} if the responder
1107      * role is successfully enabled, {@code null} otherwise.
1108      *
1109      * @param timeoutSeconds timeout to use for the responder.
1110      */
1111     @Nullable
enableRttResponder(int timeoutSeconds)1112     public ResponderConfig enableRttResponder(int timeoutSeconds) {
1113         return mWifiVendorHal.enableRttResponder(timeoutSeconds);
1114     }
1115 
1116     /**
1117      * Disable RTT responder role. Returns {@code true} if responder role is successfully disabled,
1118      * {@code false} otherwise.
1119      */
disableRttResponder()1120     public boolean disableRttResponder() {
1121         return mWifiVendorHal.disableRttResponder();
1122     }
1123 
1124     /**
1125      * Set the MAC OUI during scanning.
1126      * An OUI {Organizationally Unique Identifier} is a 24-bit number that
1127      * uniquely identifies a vendor or manufacturer.
1128      *
1129      * @param oui OUI to set.
1130      * @return true for success
1131      */
setScanningMacOui(byte[] oui)1132     public boolean setScanningMacOui(byte[] oui) {
1133         return mWifiVendorHal.setScanningMacOui(oui);
1134     }
1135 
1136     /**
1137      * Query the list of valid frequencies for the provided band.
1138      * The result depends on the on the country code that has been set.
1139      *
1140      * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
1141      * @return frequencies vector of valid frequencies (MHz), or null for error.
1142      * @throws IllegalArgumentException if band is not recognized.
1143      */
getChannelsForBand(int band)1144     public int [] getChannelsForBand(int band) {
1145         return mWifiVendorHal.getChannelsForBand(band);
1146     }
1147 
1148     /**
1149      * Indicates whether getChannelsForBand is supported.
1150      *
1151      * @return true if it is.
1152      */
isGetChannelsForBandSupported()1153     public boolean isGetChannelsForBandSupported() {
1154         return mWifiVendorHal.isGetChannelsForBandSupported();
1155     }
1156 
1157     /**
1158      * RTT (Round Trip Time) measurement capabilities of the device.
1159      */
getRttCapabilities()1160     public RttManager.RttCapabilities getRttCapabilities() {
1161         return mWifiVendorHal.getRttCapabilities();
1162     }
1163 
1164     /**
1165      * Get the APF (Android Packet Filter) capabilities of the device
1166      */
getApfCapabilities()1167     public ApfCapabilities getApfCapabilities() {
1168         return mWifiVendorHal.getApfCapabilities();
1169     }
1170 
1171     /**
1172      * Installs an APF program on this iface, replacing any existing program.
1173      *
1174      * @param filter is the android packet filter program
1175      * @return true for success
1176      */
installPacketFilter(byte[] filter)1177     public boolean installPacketFilter(byte[] filter) {
1178         return mWifiVendorHal.installPacketFilter(filter);
1179     }
1180 
1181     /**
1182      * Set country code for this AP iface.
1183      *
1184      * @param countryCode - two-letter country code (as ISO 3166)
1185      * @return true for success
1186      */
setCountryCodeHal(String countryCode)1187     public boolean setCountryCodeHal(String countryCode) {
1188         return mWifiVendorHal.setCountryCodeHal(countryCode);
1189     }
1190 
1191     //---------------------------------------------------------------------------------
1192     /* Wifi Logger commands/events */
1193     public static interface WifiLoggerEventHandler {
onRingBufferData(RingBufferStatus status, byte[] buffer)1194         void onRingBufferData(RingBufferStatus status, byte[] buffer);
onWifiAlert(int errorCode, byte[] buffer)1195         void onWifiAlert(int errorCode, byte[] buffer);
1196     }
1197 
1198     /**
1199      * Registers the logger callback and enables alerts.
1200      * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked.
1201      *
1202      * @param handler Callback to be invoked.
1203      * @return true on success, false otherwise.
1204      */
setLoggingEventHandler(WifiLoggerEventHandler handler)1205     public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) {
1206         return mWifiVendorHal.setLoggingEventHandler(handler);
1207     }
1208 
1209     /**
1210      * Control debug data collection
1211      *
1212      * @param verboseLevel 0 to 3, inclusive. 0 stops logging.
1213      * @param flags        Ignored.
1214      * @param maxInterval  Maximum interval between reports; ignore if 0.
1215      * @param minDataSize  Minimum data size in buffer for report; ignore if 0.
1216      * @param ringName     Name of the ring for which data collection is to start.
1217      * @return true for success, false otherwise.
1218      */
startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval, int minDataSize, String ringName)1219     public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval,
1220             int minDataSize, String ringName){
1221         return mWifiVendorHal.startLoggingRingBuffer(
1222                 verboseLevel, flags, maxInterval, minDataSize, ringName);
1223     }
1224 
1225     /**
1226      * Logger features exposed.
1227      * This is a no-op now, will always return -1.
1228      *
1229      * @return true on success, false otherwise.
1230      */
getSupportedLoggerFeatureSet()1231     public int getSupportedLoggerFeatureSet() {
1232         return mWifiVendorHal.getSupportedLoggerFeatureSet();
1233     }
1234 
1235     /**
1236      * Stops all logging and resets the logger callback.
1237      * This stops both the alerts and ring buffer data collection.
1238      * @return true on success, false otherwise.
1239      */
resetLogHandler()1240     public boolean resetLogHandler() {
1241         return mWifiVendorHal.resetLogHandler();
1242     }
1243 
1244     /**
1245      * Vendor-provided wifi driver version string
1246      *
1247      * @return String returned from the HAL.
1248      */
getDriverVersion()1249     public String getDriverVersion() {
1250         return mWifiVendorHal.getDriverVersion();
1251     }
1252 
1253     /**
1254      * Vendor-provided wifi firmware version string
1255      *
1256      * @return String returned from the HAL.
1257      */
getFirmwareVersion()1258     public String getFirmwareVersion() {
1259         return mWifiVendorHal.getFirmwareVersion();
1260     }
1261 
1262     public static class RingBufferStatus{
1263         String name;
1264         int flag;
1265         int ringBufferId;
1266         int ringBufferByteSize;
1267         int verboseLevel;
1268         int writtenBytes;
1269         int readBytes;
1270         int writtenRecords;
1271 
1272         // Bit masks for interpreting |flag|
1273         public static final int HAS_BINARY_ENTRIES = (1 << 0);
1274         public static final int HAS_ASCII_ENTRIES = (1 << 1);
1275         public static final int HAS_PER_PACKET_ENTRIES = (1 << 2);
1276 
1277         @Override
toString()1278         public String toString() {
1279             return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId +
1280                     " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel +
1281                     " writtenBytes: " + writtenBytes + " readBytes: " + readBytes +
1282                     " writtenRecords: " + writtenRecords;
1283         }
1284     }
1285 
1286     /**
1287      * API to get the status of all ring buffers supported by driver
1288      */
getRingBufferStatus()1289     public RingBufferStatus[] getRingBufferStatus() {
1290         return mWifiVendorHal.getRingBufferStatus();
1291     }
1292 
1293     /**
1294      * Indicates to driver that all the data has to be uploaded urgently
1295      *
1296      * @param ringName Name of the ring buffer requested.
1297      * @return true on success, false otherwise.
1298      */
getRingBufferData(String ringName)1299     public boolean getRingBufferData(String ringName) {
1300         return mWifiVendorHal.getRingBufferData(ringName);
1301     }
1302 
1303     /**
1304      * Request vendor debug info from the firmware
1305      *
1306      * @return Raw data obtained from the HAL.
1307      */
getFwMemoryDump()1308     public byte[] getFwMemoryDump() {
1309         return mWifiVendorHal.getFwMemoryDump();
1310     }
1311 
1312     /**
1313      * Request vendor debug info from the driver
1314      *
1315      * @return Raw data obtained from the HAL.
1316      */
getDriverStateDump()1317     public byte[] getDriverStateDump() {
1318         return mWifiVendorHal.getDriverStateDump();
1319     }
1320 
1321     //---------------------------------------------------------------------------------
1322     /* Packet fate API */
1323 
1324     @Immutable
1325     abstract static class FateReport {
1326         final static int USEC_PER_MSEC = 1000;
1327         // The driver timestamp is a 32-bit counter, in microseconds. This field holds the
1328         // maximal value of a driver timestamp in milliseconds.
1329         final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000);
1330         final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS");
1331 
1332         final byte mFate;
1333         final long mDriverTimestampUSec;
1334         final byte mFrameType;
1335         final byte[] mFrameBytes;
1336         final long mEstimatedWallclockMSec;
1337 
FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes)1338         FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1339             mFate = fate;
1340             mDriverTimestampUSec = driverTimestampUSec;
1341             mEstimatedWallclockMSec =
1342                     convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec);
1343             mFrameType = frameType;
1344             mFrameBytes = frameBytes;
1345         }
1346 
toTableRowString()1347         public String toTableRowString() {
1348             StringWriter sw = new StringWriter();
1349             PrintWriter pw = new PrintWriter(sw);
1350             FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
1351             dateFormatter.setTimeZone(TimeZone.getDefault());
1352             pw.format("%-15s  %12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1353                     mDriverTimestampUSec,
1354                     dateFormatter.format(new Date(mEstimatedWallclockMSec)),
1355                     directionToString(), fateToString(), parser.mMostSpecificProtocolString,
1356                     parser.mTypeString, parser.mResultString);
1357             return sw.toString();
1358         }
1359 
toVerboseStringWithPiiAllowed()1360         public String toVerboseStringWithPiiAllowed() {
1361             StringWriter sw = new StringWriter();
1362             PrintWriter pw = new PrintWriter(sw);
1363             FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
1364             pw.format("Frame direction: %s\n", directionToString());
1365             pw.format("Frame timestamp: %d\n", mDriverTimestampUSec);
1366             pw.format("Frame fate: %s\n", fateToString());
1367             pw.format("Frame type: %s\n", frameTypeToString(mFrameType));
1368             pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString);
1369             pw.format("Frame protocol type: %s\n", parser.mTypeString);
1370             pw.format("Frame length: %d\n", mFrameBytes.length);
1371             pw.append("Frame bytes");
1372             pw.append(HexDump.dumpHexString(mFrameBytes));  // potentially contains PII
1373             pw.append("\n");
1374             return sw.toString();
1375         }
1376 
1377         /* Returns a header to match the output of toTableRowString(). */
getTableHeader()1378         public static String getTableHeader() {
1379             StringWriter sw = new StringWriter();
1380             PrintWriter pw = new PrintWriter(sw);
1381             pw.format("\n%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1382                     "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result");
1383             pw.format("%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1384                     "---------", "--------", "---------", "----", "--------", "----", "------");
1385             return sw.toString();
1386         }
1387 
directionToString()1388         protected abstract String directionToString();
1389 
fateToString()1390         protected abstract String fateToString();
1391 
frameTypeToString(byte frameType)1392         private static String frameTypeToString(byte frameType) {
1393             switch (frameType) {
1394                 case WifiLoggerHal.FRAME_TYPE_UNKNOWN:
1395                     return "unknown";
1396                 case WifiLoggerHal.FRAME_TYPE_ETHERNET_II:
1397                     return "data";
1398                 case WifiLoggerHal.FRAME_TYPE_80211_MGMT:
1399                     return "802.11 management";
1400                 default:
1401                     return Byte.toString(frameType);
1402             }
1403         }
1404 
1405         /**
1406          * Converts a driver timestamp to a wallclock time, based on the current
1407          * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of
1408          * microseconds, with the same base as BOOTTIME.
1409          */
convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec)1410         private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) {
1411             final long wallclockMillisNow = System.currentTimeMillis();
1412             final long boottimeMillisNow = SystemClock.elapsedRealtime();
1413             final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC;
1414 
1415             long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC;
1416             if (boottimeTimestampMillis < driverTimestampMillis) {
1417                 // The 32-bit microsecond count has wrapped between the time that the driver
1418                 // recorded the packet, and the call to this function. Adjust the BOOTTIME
1419                 // timestamp, to compensate.
1420                 //
1421                 // Note that overflow is not a concern here, since the result is less than
1422                 // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above,
1423                 // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since
1424                 // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit
1425                 // within a long.
1426                 boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC;
1427             }
1428 
1429             final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis;
1430             return wallclockMillisNow - millisSincePacketTimestamp;
1431         }
1432     }
1433 
1434     /**
1435      * Represents the fate information for one outbound packet.
1436      */
1437     @Immutable
1438     public static final class TxFateReport extends FateReport {
TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes)1439         TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1440             super(fate, driverTimestampUSec, frameType, frameBytes);
1441         }
1442 
1443         @Override
directionToString()1444         protected String directionToString() {
1445             return "TX";
1446         }
1447 
1448         @Override
fateToString()1449         protected String fateToString() {
1450             switch (mFate) {
1451                 case WifiLoggerHal.TX_PKT_FATE_ACKED:
1452                     return "acked";
1453                 case WifiLoggerHal.TX_PKT_FATE_SENT:
1454                     return "sent";
1455                 case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED:
1456                     return "firmware queued";
1457                 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID:
1458                     return "firmware dropped (invalid frame)";
1459                 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS:
1460                     return "firmware dropped (no bufs)";
1461                 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER:
1462                     return "firmware dropped (other)";
1463                 case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED:
1464                     return "driver queued";
1465                 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID:
1466                     return "driver dropped (invalid frame)";
1467                 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS:
1468                     return "driver dropped (no bufs)";
1469                 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER:
1470                     return "driver dropped (other)";
1471                 default:
1472                     return Byte.toString(mFate);
1473             }
1474         }
1475     }
1476 
1477     /**
1478      * Represents the fate information for one inbound packet.
1479      */
1480     @Immutable
1481     public static final class RxFateReport extends FateReport {
RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes)1482         RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1483             super(fate, driverTimestampUSec, frameType, frameBytes);
1484         }
1485 
1486         @Override
directionToString()1487         protected String directionToString() {
1488             return "RX";
1489         }
1490 
1491         @Override
fateToString()1492         protected String fateToString() {
1493             switch (mFate) {
1494                 case WifiLoggerHal.RX_PKT_FATE_SUCCESS:
1495                     return "success";
1496                 case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED:
1497                     return "firmware queued";
1498                 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER:
1499                     return "firmware dropped (filter)";
1500                 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID:
1501                     return "firmware dropped (invalid frame)";
1502                 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS:
1503                     return "firmware dropped (no bufs)";
1504                 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER:
1505                     return "firmware dropped (other)";
1506                 case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED:
1507                     return "driver queued";
1508                 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER:
1509                     return "driver dropped (filter)";
1510                 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID:
1511                     return "driver dropped (invalid frame)";
1512                 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS:
1513                     return "driver dropped (no bufs)";
1514                 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER:
1515                     return "driver dropped (other)";
1516                 default:
1517                     return Byte.toString(mFate);
1518             }
1519         }
1520     }
1521 
1522     /**
1523      * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started.
1524      *
1525      * @return true for success, false otherwise.
1526      */
startPktFateMonitoring()1527     public boolean startPktFateMonitoring() {
1528         return mWifiVendorHal.startPktFateMonitoring();
1529     }
1530 
1531     /**
1532      * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started.
1533      *
1534      * @return true for success, false otherwise.
1535      */
getTxPktFates(TxFateReport[] reportBufs)1536     public boolean getTxPktFates(TxFateReport[] reportBufs) {
1537         return mWifiVendorHal.getTxPktFates(reportBufs);
1538     }
1539 
1540     /**
1541      * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started.
1542      */
getRxPktFates(RxFateReport[] reportBufs)1543     public boolean getRxPktFates(RxFateReport[] reportBufs) {
1544         return mWifiVendorHal.getRxPktFates(reportBufs);
1545     }
1546 
1547     /**
1548      * Start sending the specified keep alive packets periodically.
1549      *
1550      * @param slot Integer used to identify each request.
1551      * @param keepAlivePacket Raw packet contents to send.
1552      * @param period Period to use for sending these packets.
1553      * @return 0 for success, -1 for error
1554      */
startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket, int period)1555     public int startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket,
1556                                            int period) {
1557         String[] macAddrStr = getMacAddress().split(":");
1558         byte[] srcMac = new byte[6];
1559         for (int i = 0; i < 6; i++) {
1560             Integer hexVal = Integer.parseInt(macAddrStr[i], 16);
1561             srcMac[i] = hexVal.byteValue();
1562         }
1563         return mWifiVendorHal.startSendingOffloadedPacket(
1564                 slot, srcMac, keepAlivePacket, period);
1565     }
1566 
1567     /**
1568      * Stop sending the specified keep alive packets.
1569      *
1570      * @param slot id - same as startSendingOffloadedPacket call.
1571      * @return 0 for success, -1 for error
1572      */
stopSendingOffloadedPacket(int slot)1573     public int stopSendingOffloadedPacket(int slot) {
1574         return mWifiVendorHal.stopSendingOffloadedPacket(slot);
1575     }
1576 
1577     public static interface WifiRssiEventHandler {
onRssiThresholdBreached(byte curRssi)1578         void onRssiThresholdBreached(byte curRssi);
1579     }
1580 
1581     /**
1582      * Start RSSI monitoring on the currently connected access point.
1583      *
1584      * @param maxRssi          Maximum RSSI threshold.
1585      * @param minRssi          Minimum RSSI threshold.
1586      * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi
1587      * @return 0 for success, -1 for failure
1588      */
startRssiMonitoring(byte maxRssi, byte minRssi, WifiRssiEventHandler rssiEventHandler)1589     public int startRssiMonitoring(byte maxRssi, byte minRssi,
1590                                    WifiRssiEventHandler rssiEventHandler) {
1591         return mWifiVendorHal.startRssiMonitoring(maxRssi, minRssi, rssiEventHandler);
1592     }
1593 
stopRssiMonitoring()1594     public int stopRssiMonitoring() {
1595         return mWifiVendorHal.stopRssiMonitoring();
1596     }
1597 
1598     /**
1599      * Fetch the host wakeup reasons stats from wlan driver.
1600      *
1601      * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver.
1602      */
getWlanWakeReasonCount()1603     public WifiWakeReasonAndCounts getWlanWakeReasonCount() {
1604         return mWifiVendorHal.getWlanWakeReasonCount();
1605     }
1606 
1607     /**
1608      * Enable/Disable Neighbour discovery offload functionality in the firmware.
1609      *
1610      * @param enabled true to enable, false to disable.
1611      * @return true for success, false otherwise.
1612      */
configureNeighborDiscoveryOffload(boolean enabled)1613     public boolean configureNeighborDiscoveryOffload(boolean enabled) {
1614         return mWifiVendorHal.configureNeighborDiscoveryOffload(enabled);
1615     }
1616 
1617     // Firmware roaming control.
1618 
1619     /**
1620      * Class to retrieve firmware roaming capability parameters.
1621      */
1622     public static class RoamingCapabilities {
1623         public int  maxBlacklistSize;
1624         public int  maxWhitelistSize;
1625     }
1626 
1627     /**
1628      * Query the firmware roaming capabilities.
1629      * @return true for success, false otherwise.
1630      */
getRoamingCapabilities(RoamingCapabilities capabilities)1631     public boolean getRoamingCapabilities(RoamingCapabilities capabilities) {
1632         return mWifiVendorHal.getRoamingCapabilities(capabilities);
1633     }
1634 
1635     /**
1636      * Macros for controlling firmware roaming.
1637      */
1638     public static final int DISABLE_FIRMWARE_ROAMING = 0;
1639     public static final int ENABLE_FIRMWARE_ROAMING = 1;
1640 
1641     /**
1642      * Enable/disable firmware roaming.
1643      *
1644      * @return error code returned from HAL.
1645      */
enableFirmwareRoaming(int state)1646     public int enableFirmwareRoaming(int state) {
1647         return mWifiVendorHal.enableFirmwareRoaming(state);
1648     }
1649 
1650     /**
1651      * Class for specifying the roaming configurations.
1652      */
1653     public static class RoamingConfig {
1654         public ArrayList<String> blacklistBssids;
1655         public ArrayList<String> whitelistSsids;
1656     }
1657 
1658     /**
1659      * Set firmware roaming configurations.
1660      */
configureRoaming(RoamingConfig config)1661     public boolean configureRoaming(RoamingConfig config) {
1662         Log.d(mTAG, "configureRoaming ");
1663         return mWifiVendorHal.configureRoaming(config);
1664     }
1665 
1666     /**
1667      * Reset firmware roaming configuration.
1668      */
resetRoamingConfiguration()1669     public boolean resetRoamingConfiguration() {
1670         // Pass in an empty RoamingConfig object which translates to zero size
1671         // blacklist and whitelist to reset the firmware roaming configuration.
1672         return mWifiVendorHal.configureRoaming(new RoamingConfig());
1673     }
1674 
1675     /**
1676      * Tx power level scenarios that can be selected.
1677      */
1678     public static final int TX_POWER_SCENARIO_NORMAL = 0;
1679     public static final int TX_POWER_SCENARIO_VOICE_CALL = 1;
1680 
1681     /**
1682      * Select one of the pre-configured TX power level scenarios or reset it back to normal.
1683      * Primarily used for meeting SAR requirements during voice calls.
1684      *
1685      * @param scenario Should be one {@link #TX_POWER_SCENARIO_NORMAL} or
1686      *        {@link #TX_POWER_SCENARIO_VOICE_CALL}.
1687      * @return true for success; false for failure or if the HAL version does not support this API.
1688      */
selectTxPowerScenario(int scenario)1689     public boolean selectTxPowerScenario(int scenario) {
1690         return mWifiVendorHal.selectTxPowerScenario(scenario);
1691     }
1692 
1693     /********************************************************
1694      * JNI operations
1695      ********************************************************/
1696     /* Register native functions */
1697     static {
1698         /* Native functions are defined in libwifi-service.so */
1699         System.loadLibrary("wifi-service");
registerNatives()1700         registerNatives();
1701     }
1702 
registerNatives()1703     private static native int registerNatives();
1704     /* kernel logging support */
readKernelLogNative()1705     private static native byte[] readKernelLogNative();
1706 
1707     /**
1708      * Fetches the latest kernel logs.
1709      */
readKernelLog()1710     public synchronized String readKernelLog() {
1711         byte[] bytes = readKernelLogNative();
1712         if (bytes != null) {
1713             CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
1714             try {
1715                 CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
1716                 return decoded.toString();
1717             } catch (CharacterCodingException cce) {
1718                 return new String(bytes, StandardCharsets.ISO_8859_1);
1719             }
1720         } else {
1721             return "*** failed to read kernel log ***";
1722         }
1723     }
1724 }
1725