WifiNative.java revision 3e240b2bfb6fefe8b91ad68e8a12b652b4136c69
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wifi;
18
19import android.annotation.Nullable;
20import android.net.apf.ApfCapabilities;
21import android.net.wifi.IApInterface;
22import android.net.wifi.IClientInterface;
23import android.net.wifi.RttManager;
24import android.net.wifi.RttManager.ResponderConfig;
25import android.net.wifi.ScanResult;
26import android.net.wifi.WifiConfiguration;
27import android.net.wifi.WifiLinkLayerStats;
28import android.net.wifi.WifiScanner;
29import android.net.wifi.WifiWakeReasonAndCounts;
30import android.net.wifi.p2p.WifiP2pConfig;
31import android.net.wifi.p2p.WifiP2pGroup;
32import android.net.wifi.p2p.WifiP2pGroupList;
33import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
34import android.os.SystemClock;
35import android.util.Log;
36import android.util.SparseArray;
37
38import com.android.internal.annotations.Immutable;
39import com.android.internal.util.HexDump;
40import com.android.server.connectivity.KeepalivePacketData;
41import com.android.server.wifi.util.FrameParser;
42
43import java.io.PrintWriter;
44import java.io.StringWriter;
45import java.nio.ByteBuffer;
46import java.nio.CharBuffer;
47import java.nio.charset.CharacterCodingException;
48import java.nio.charset.CharsetDecoder;
49import java.nio.charset.StandardCharsets;
50import java.text.SimpleDateFormat;
51import java.util.ArrayList;
52import java.util.Date;
53import java.util.Map;
54import java.util.Objects;
55import java.util.Set;
56import java.util.TimeZone;
57
58
59/**
60 * Native calls for bring up/shut down of the supplicant daemon and for
61 * sending requests to the supplicant daemon
62 *
63 * {@hide}
64 */
65public class WifiNative {
66    private final String mTAG;
67    private final String mInterfaceName;
68    private final SupplicantStaIfaceHal mSupplicantStaIfaceHal;
69    private final SupplicantP2pIfaceHal mSupplicantP2pIfaceHal;
70    private final WifiVendorHal mWifiVendorHal;
71    private final WificondControl mWificondControl;
72
73    public WifiNative(String interfaceName, WifiVendorHal vendorHal,
74                      SupplicantStaIfaceHal staIfaceHal, SupplicantP2pIfaceHal p2pIfaceHal,
75                      WificondControl condControl) {
76        mTAG = "WifiNative-" + interfaceName;
77        mInterfaceName = interfaceName;
78        mWifiVendorHal = vendorHal;
79        mSupplicantStaIfaceHal = staIfaceHal;
80        mSupplicantP2pIfaceHal = p2pIfaceHal;
81        mWificondControl = condControl;
82    }
83
84    public String getInterfaceName() {
85        return mInterfaceName;
86    }
87
88    /**
89     * Enable verbose logging for all sub modules.
90     */
91    public void enableVerboseLogging(int verbose) {
92        mWificondControl.enableVerboseLogging(verbose > 0 ? true : false);
93        mSupplicantStaIfaceHal.enableVerboseLogging(verbose > 0);
94        mWifiVendorHal.enableVerboseLogging(verbose > 0);
95    }
96
97   /********************************************************
98    * Native Initialization/Deinitialization
99    ********************************************************/
100
101   /**
102    * Setup wifi native for Client mode operations.
103    *
104    * 1. Starts the Wifi HAL and configures it in client/STA mode.
105    * 2. Setup Wificond to operate in client mode and retrieve the handle to use for client
106    * operations.
107    *
108    * @return An IClientInterface as wificond client interface binder handler.
109    * Returns null on failure.
110    */
111    public IClientInterface setupForClientMode() {
112        if (!startHal(true)) {
113            // TODO(b/34859006): Handle failures.
114            Log.e(mTAG, "Failed to start HAL for client mode");
115        }
116        return mWificondControl.setupDriverForClientMode();
117    }
118
119    /**
120     * Setup wifi native for AP mode operations.
121     *
122     * 1. Starts the Wifi HAL and configures it in AP mode.
123     * 2. Setup Wificond to operate in AP mode and retrieve the handle to use for ap operations.
124     *
125     * @return An IApInterface as wificond Ap interface binder handler.
126     * Returns null on failure.
127     */
128    public IApInterface setupForSoftApMode() {
129        if (!startHal(false)) {
130            // TODO(b/34859006): Handle failures.
131            Log.e(mTAG, "Failed to start HAL for AP mode");
132        }
133        return mWificondControl.setupDriverForSoftApMode();
134    }
135
136    /**
137     * Teardown all mode configurations in wifi native.
138     *
139     * 1. Tears down all the interfaces from Wificond.
140     * 2. Stops the Wifi HAL.
141     *
142     * @return Returns true on success.
143     */
144    public boolean tearDown() {
145        if (!mWificondControl.tearDownInterfaces()) {
146            // TODO(b/34859006): Handle failures.
147            Log.e(mTAG, "Failed to teardown interfaces from Wificond");
148            return false;
149        }
150        stopHal();
151        return true;
152    }
153
154    /********************************************************
155     * Wificond operations
156     ********************************************************/
157    /**
158     * Result of a signal poll.
159     */
160    public static class SignalPollResult {
161        // RSSI value in dBM.
162        public int currentRssi;
163        //Transmission bit rate in Mbps.
164        public int txBitrate;
165        // Association frequency in MHz.
166        public int associationFrequency;
167    }
168
169    /**
170     * WiFi interface transimission counters.
171     */
172    public static class TxPacketCounters {
173        // Number of successfully transmitted packets.
174        public int txSucceeded;
175        // Number of tramsmission failures.
176        public int txFailed;
177    }
178
179    /**
180    * Disable wpa_supplicant via wificond.
181    * @return Returns true on success.
182    */
183    public boolean disableSupplicant() {
184        return mWificondControl.disableSupplicant();
185    }
186
187    /**
188    * Enable wpa_supplicant via wificond.
189    * @return Returns true on success.
190    */
191    public boolean enableSupplicant() {
192        return mWificondControl.enableSupplicant();
193    }
194
195    /**
196    * Request signal polling to wificond.
197    * Returns an SignalPollResult object.
198    * Returns null on failure.
199    */
200    public SignalPollResult signalPoll() {
201        return mWificondControl.signalPoll();
202    }
203
204    /**
205     * Fetch TX packet counters on current connection from wificond.
206    * Returns an TxPacketCounters object.
207    * Returns null on failure.
208    */
209    public TxPacketCounters getTxPacketCounters() {
210        return mWificondControl.getTxPacketCounters();
211    }
212
213    /**
214     * Start a scan using wificond for the given parameters.
215     * @param freqs list of frequencies to scan for, if null scan all supported channels.
216     * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
217     * @return Returns true on success.
218     */
219    public boolean scan(Set<Integer> freqs, Set<String> hiddenNetworkSSIDs) {
220        return mWificondControl.scan(freqs, hiddenNetworkSSIDs);
221    }
222
223    /**
224     * Fetch the latest scan result from kernel via wificond.
225     * @return Returns an ArrayList of ScanDetail.
226     * Returns an empty ArrayList on failure.
227     */
228    public ArrayList<ScanDetail> getScanResults() {
229        return mWificondControl.getScanResults();
230    }
231
232    /**
233     * Start PNO scan.
234     * @param pnoSettings Pno scan configuration.
235     * @return true on success.
236     */
237    public boolean startPnoScan(PnoSettings pnoSettings) {
238        return mWificondControl.startPnoScan(pnoSettings);
239    }
240
241    /**
242     * Stop PNO scan.
243     * @return true on success.
244     */
245    public boolean stopPnoScan() {
246        return mWificondControl.stopPnoScan();
247    }
248
249    /********************************************************
250     * Supplicant operations
251     ********************************************************/
252
253    /**
254     * This method is called repeatedly until the connection to wpa_supplicant is established.
255     *
256     * @return true if connection is established, false otherwise.
257     * TODO: Add unit tests for these once we remove the legacy code.
258     */
259    public boolean connectToStaSupplicant() {
260        // Start initialization if not already started.
261        if (!mSupplicantStaIfaceHal.isInitializationStarted()
262                && !mSupplicantStaIfaceHal.initialize()) {
263            return false;
264        }
265        // Check if the initialization is complete.
266        return mSupplicantStaIfaceHal.isInitializationComplete();
267    }
268
269    /**
270     * This method is called repeatedly until the connection to wpa_supplicant is established.
271     *
272     * @return true if connection is established, false otherwise.
273     * TODO: Add unit tests for these once we remove the legacy code.
274     */
275    public boolean connectToP2pSupplicant() {
276        // Start initialization if not already started.
277        if (!mSupplicantP2pIfaceHal.isInitializationStarted()
278                && !mSupplicantP2pIfaceHal.initialize()) {
279            return false;
280        }
281        // Check if the initialization is complete.
282        return mSupplicantP2pIfaceHal.isInitializationComplete();
283    }
284
285    /**
286     * Close supplicant connection.
287     */
288    public void closeSupplicantConnection() {
289        // Nothing to do for HIDL.
290    }
291
292    /**
293     * Set supplicant log level
294     *
295     * @param turnOnVerbose Whether to turn on verbose logging or not.
296     */
297    public void setSupplicantLogLevel(boolean turnOnVerbose) {
298        int logLevel = turnOnVerbose
299                ? SupplicantStaIfaceHal.LOG_LEVEL_DEBUG
300                : SupplicantStaIfaceHal.LOG_LEVEL_INFO;
301        mSupplicantStaIfaceHal.setLogLevel(logLevel);
302    }
303
304    /**
305     * Trigger a reconnection if the iface is disconnected.
306     *
307     * @return true if request is sent successfully, false otherwise.
308     */
309    public boolean reconnect() {
310        return mSupplicantStaIfaceHal.reconnect();
311    }
312
313    /**
314     * Trigger a reassociation even if the iface is currently connected.
315     *
316     * @return true if request is sent successfully, false otherwise.
317     */
318    public boolean reassociate() {
319        return mSupplicantStaIfaceHal.reassociate();
320    }
321
322    /**
323     * Trigger a disconnection from the currently connected network.
324     *
325     * @return true if request is sent successfully, false otherwise.
326     */
327    public boolean disconnect() {
328        return mSupplicantStaIfaceHal.disconnect();
329    }
330
331    /**
332     * Makes a callback to HIDL to getMacAddress from supplicant
333     *
334     * @return string containing the MAC address, or null on a failed call
335     */
336    public String getMacAddress() {
337        return mSupplicantStaIfaceHal.getMacAddress();
338    }
339
340    /**
341     * Start filtering out Multicast V4 packets
342     * @return {@code true} if the operation succeeded, {@code false} otherwise
343     *
344     * Multicast filtering rules work as follows:
345     *
346     * The driver can filter multicast (v4 and/or v6) and broadcast packets when in
347     * a power optimized mode (typically when screen goes off).
348     *
349     * In order to prevent the driver from filtering the multicast/broadcast packets, we have to
350     * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective
351     *
352     * DRIVER RXFILTER-ADD Num
353     *   where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6
354     *
355     * and DRIVER RXFILTER-START
356     * In order to stop the usage of these rules, we do
357     *
358     * DRIVER RXFILTER-STOP
359     * DRIVER RXFILTER-REMOVE Num
360     *   where Num is as described for RXFILTER-ADD
361     *
362     * The  SETSUSPENDOPT driver command overrides the filtering rules
363     */
364    public boolean startFilteringMulticastV4Packets() {
365        return mSupplicantStaIfaceHal.stopRxFilter()
366                && mSupplicantStaIfaceHal.removeRxFilter(
367                SupplicantStaIfaceHal.RX_FILTER_TYPE_V4_MULTICAST)
368                && mSupplicantStaIfaceHal.startRxFilter();
369    }
370
371    /**
372     * Stop filtering out Multicast V4 packets.
373     * @return {@code true} if the operation succeeded, {@code false} otherwise
374     */
375    public boolean stopFilteringMulticastV4Packets() {
376        return mSupplicantStaIfaceHal.stopRxFilter()
377                && mSupplicantStaIfaceHal.addRxFilter(
378                SupplicantStaIfaceHal.RX_FILTER_TYPE_V4_MULTICAST)
379                && mSupplicantStaIfaceHal.startRxFilter();
380    }
381
382    /**
383     * Start filtering out Multicast V6 packets
384     * @return {@code true} if the operation succeeded, {@code false} otherwise
385     */
386    public boolean startFilteringMulticastV6Packets() {
387        return mSupplicantStaIfaceHal.stopRxFilter()
388                && mSupplicantStaIfaceHal.removeRxFilter(
389                SupplicantStaIfaceHal.RX_FILTER_TYPE_V6_MULTICAST)
390                && mSupplicantStaIfaceHal.startRxFilter();
391    }
392
393    /**
394     * Stop filtering out Multicast V6 packets.
395     * @return {@code true} if the operation succeeded, {@code false} otherwise
396     */
397    public boolean stopFilteringMulticastV6Packets() {
398        return mSupplicantStaIfaceHal.stopRxFilter()
399                && mSupplicantStaIfaceHal.addRxFilter(
400                SupplicantStaIfaceHal.RX_FILTER_TYPE_V6_MULTICAST)
401                && mSupplicantStaIfaceHal.startRxFilter();
402    }
403
404    public static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED  =
405            SupplicantStaIfaceHal.BT_COEX_MODE_ENABLED;
406    public static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED =
407            SupplicantStaIfaceHal.BT_COEX_MODE_DISABLED;
408    public static final int BLUETOOTH_COEXISTENCE_MODE_SENSE    =
409            SupplicantStaIfaceHal.BT_COEX_MODE_SENSE;
410    /**
411      * Sets the bluetooth coexistence mode.
412      *
413      * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED},
414      *            {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or
415      *            {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}.
416      * @return Whether the mode was successfully set.
417      */
418    public boolean setBluetoothCoexistenceMode(int mode) {
419        return mSupplicantStaIfaceHal.setBtCoexistenceMode((byte) mode);
420    }
421
422    /**
423     * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
424     * some of the low-level scan parameters used by the driver are changed to
425     * reduce interference with A2DP streaming.
426     *
427     * @param setCoexScanMode whether to enable or disable this mode
428     * @return {@code true} if the command succeeded, {@code false} otherwise.
429     */
430    public boolean setBluetoothCoexistenceScanMode(boolean setCoexScanMode) {
431        return mSupplicantStaIfaceHal.setBtCoexistenceScanModeEnabled(setCoexScanMode);
432    }
433
434    /**
435     * Enable or disable suspend mode optimizations.
436     *
437     * @param enabled true to enable, false otherwise.
438     * @return true if request is sent successfully, false otherwise.
439     */
440    public boolean setSuspendOptimizations(boolean enabled) {
441        return mSupplicantStaIfaceHal.setSuspendModeEnabled(enabled);
442    }
443
444    /**
445     * Set country code.
446     *
447     * @param countryCode 2 byte ASCII string. For ex: US, CA.
448     * @return true if request is sent successfully, false otherwise.
449     */
450    public boolean setCountryCode(String countryCode) {
451        return mSupplicantStaIfaceHal.setCountryCode(countryCode);
452    }
453
454    /**
455     * Initiate TDLS discover and setup or teardown with the specified peer.
456     *
457     * @param macAddr MAC Address of the peer.
458     * @param enable true to start discovery and setup, false to teardown.
459     */
460    public void startTdls(String macAddr, boolean enable) {
461        if (enable) {
462            mSupplicantStaIfaceHal.initiateTdlsDiscover(macAddr);
463            mSupplicantStaIfaceHal.initiateTdlsSetup(macAddr);
464        } else {
465            mSupplicantStaIfaceHal.initiateTdlsTeardown(macAddr);
466        }
467    }
468
469    /**
470     * Start WPS pin display operation with the specified peer.
471     *
472     * @param bssid BSSID of the peer.
473     * @return true if request is sent successfully, false otherwise.
474     */
475    public boolean startWpsPbc(String bssid) {
476        return mSupplicantStaIfaceHal.startWpsPbc(bssid);
477    }
478
479    /**
480     * Start WPS pin keypad operation with the specified pin.
481     *
482     * @param pin Pin to be used.
483     * @return true if request is sent successfully, false otherwise.
484     */
485    public boolean startWpsPinKeypad(String pin) {
486        return mSupplicantStaIfaceHal.startWpsPinKeypad(pin);
487    }
488
489    /**
490     * Start WPS pin display operation with the specified peer.
491     *
492     * @param bssid BSSID of the peer.
493     * @return new pin generated on success, null otherwise.
494     */
495    public String startWpsPinDisplay(String bssid) {
496        return mSupplicantStaIfaceHal.startWpsPinDisplay(bssid);
497    }
498
499    /**
500     * Sets whether to use external sim for SIM/USIM processing.
501     *
502     * @param external true to enable, false otherwise.
503     * @return true if request is sent successfully, false otherwise.
504     */
505    public boolean setExternalSim(boolean external) {
506        return mSupplicantStaIfaceHal.setExternalSim(external);
507    }
508
509    /**
510     * Sim auth response types.
511     */
512    public static final String SIM_AUTH_RESP_TYPE_GSM_AUTH = "GSM-AUTH";
513    public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTH = "UMTS-AUTH";
514    public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTS = "UMTS-AUTS";
515
516    /**
517     * Send the sim auth response for the currently configured network.
518     *
519     * @param type |GSM-AUTH|, |UMTS-AUTH| or |UMTS-AUTS|.
520     * @param response Response params.
521     * @return true if succeeds, false otherwise.
522     */
523    public boolean simAuthResponse(int id, String type, String response) {
524        if (SIM_AUTH_RESP_TYPE_GSM_AUTH.equals(type)) {
525            return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthResponse(response);
526        } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTH.equals(type)) {
527            return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthResponse(response);
528        } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTS.equals(type)) {
529            return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAutsResponse(response);
530        } else {
531            return false;
532        }
533    }
534
535    /**
536     * Send the eap sim gsm auth failure for the currently configured network.
537     *
538     * @return true if succeeds, false otherwise.
539     */
540    public boolean simAuthFailedResponse(int id) {
541        return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthFailure();
542    }
543
544    /**
545     * Send the eap sim umts auth failure for the currently configured network.
546     *
547     * @return true if succeeds, false otherwise.
548     */
549    public boolean umtsAuthFailedResponse(int id) {
550        return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthFailure();
551    }
552
553    /**
554     * Send the eap identity response for the currently configured network.
555     *
556     * @param response String to send.
557     * @return true if succeeds, false otherwise.
558     */
559    public boolean simIdentityResponse(int id, String response) {
560        return mSupplicantStaIfaceHal.sendCurrentNetworkEapIdentityResponse(response);
561    }
562
563    /**
564     * Start WPS pin registrar operation with the specified peer and pin.
565     *
566     * @param bssid BSSID of the peer.
567     * @param pin Pin to be used.
568     * @return true if request is sent successfully, false otherwise.
569     */
570    public boolean startWpsRegistrar(String bssid, String pin) {
571        return mSupplicantStaIfaceHal.startWpsRegistrar(bssid, pin);
572    }
573
574    /**
575     * Cancels any ongoing WPS requests.
576     *
577     * @return true if request is sent successfully, false otherwise.
578     */
579    public boolean cancelWps() {
580        return mSupplicantStaIfaceHal.cancelWps();
581    }
582
583    /**
584     * Set WPS device name.
585     *
586     * @param name String to be set.
587     * @return true if request is sent successfully, false otherwise.
588     */
589    public boolean setDeviceName(String name) {
590        return mSupplicantStaIfaceHal.setWpsDeviceName(name);
591    }
592
593    /**
594     * Set WPS device type.
595     *
596     * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg>
597     * @return true if request is sent successfully, false otherwise.
598     */
599    public boolean setDeviceType(String type) {
600        return mSupplicantStaIfaceHal.setWpsDeviceType(type);
601    }
602
603    /**
604     * Set WPS config methods
605     *
606     * @param cfg List of config methods.
607     * @return true if request is sent successfully, false otherwise.
608     */
609    public boolean setConfigMethods(String cfg) {
610        return mSupplicantStaIfaceHal.setWpsConfigMethods(cfg);
611    }
612
613    /**
614     * Set WPS manufacturer.
615     *
616     * @param value String to be set.
617     * @return true if request is sent successfully, false otherwise.
618     */
619    public boolean setManufacturer(String value) {
620        return mSupplicantStaIfaceHal.setWpsManufacturer(value);
621    }
622
623    /**
624     * Set WPS model name.
625     *
626     * @param value String to be set.
627     * @return true if request is sent successfully, false otherwise.
628     */
629    public boolean setModelName(String value) {
630        return mSupplicantStaIfaceHal.setWpsModelName(value);
631    }
632
633    /**
634     * Set WPS model number.
635     *
636     * @param value String to be set.
637     * @return true if request is sent successfully, false otherwise.
638     */
639    public boolean setModelNumber(String value) {
640        return mSupplicantStaIfaceHal.setWpsModelNumber(value);
641    }
642
643    /**
644     * Set WPS serial number.
645     *
646     * @param value String to be set.
647     * @return true if request is sent successfully, false otherwise.
648     */
649    public boolean setSerialNumber(String value) {
650        return mSupplicantStaIfaceHal.setWpsSerialNumber(value);
651    }
652
653    /**
654     * Enable or disable power save mode.
655     *
656     * @param enabled true to enable, false to disable.
657     */
658    public void setPowerSave(boolean enabled) {
659        mSupplicantStaIfaceHal.setPowerSave(enabled);
660    }
661
662    /**
663     * Set concurrency priority between P2P & STA operations.
664     *
665     * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations,
666     *                            false otherwise.
667     * @return true if request is sent successfully, false otherwise.
668     */
669    public boolean setConcurrencyPriority(boolean isStaHigherPriority) {
670        return mSupplicantStaIfaceHal.setConcurrencyPriority(isStaHigherPriority);
671    }
672
673    /**
674     * Enable/Disable auto reconnect functionality in wpa_supplicant.
675     *
676     * @param enable true to enable auto reconnecting, false to disable.
677     * @return true if request is sent successfully, false otherwise.
678     */
679    public boolean enableStaAutoReconnect(boolean enable) {
680        return mSupplicantStaIfaceHal.enableAutoReconnect(enable);
681    }
682
683    /**
684     * Migrate all the configured networks from wpa_supplicant.
685     *
686     * @param configs       Map of configuration key to configuration objects corresponding to all
687     *                      the networks.
688     * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf
689     * @return Max priority of all the configs.
690     */
691    public boolean migrateNetworksFromSupplicant(Map<String, WifiConfiguration> configs,
692                                                 SparseArray<Map<String, String>> networkExtras) {
693        return mSupplicantStaIfaceHal.loadNetworks(configs, networkExtras);
694    }
695
696    /**
697     * Add the provided network configuration to wpa_supplicant and initiate connection to it.
698     * This method does the following:
699     * 1. Triggers disconnect command to wpa_supplicant (if |shouldDisconnect| is true).
700     * 2. Remove any existing network in wpa_supplicant.
701     * 3. Add a new network to wpa_supplicant.
702     * 4. Save the provided configuration to wpa_supplicant.
703     * 5. Select the new network in wpa_supplicant.
704     * 6. Triggers reconnect command to wpa_supplicant.
705     *
706     * @param configuration WifiConfiguration parameters for the provided network.
707     * @param shouldDisconnect whether to trigger a disconnection or not.
708     * @return {@code true} if it succeeds, {@code false} otherwise
709     */
710    public boolean connectToNetwork(WifiConfiguration configuration, boolean shouldDisconnect) {
711        return mSupplicantStaIfaceHal.connectToNetwork(configuration, shouldDisconnect);
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. First check if we're attempting to connect to the same network as we currently have
719     * configured.
720     * 2. Set the new bssid for the network in wpa_supplicant.
721     * 3. Triggers reassociate command to wpa_supplicant.
722     *
723     * @param configuration WifiConfiguration parameters for the provided network.
724     * @return {@code true} if it succeeds, {@code false} otherwise
725     */
726    public boolean roamToNetwork(WifiConfiguration configuration) {
727        return mSupplicantStaIfaceHal.roamToNetwork(configuration);
728    }
729
730    /**
731     * Get the framework network ID corresponding to the provided supplicant network ID for the
732     * network configured in wpa_supplicant.
733     *
734     * @param supplicantNetworkId network ID in wpa_supplicant for the network.
735     * @return Corresponding framework network ID if found, -1 if network not found.
736     */
737    public int getFrameworkNetworkId(int supplicantNetworkId) {
738        return supplicantNetworkId;
739    }
740
741    /**
742     * Remove all the networks.
743     *
744     * @return {@code true} if it succeeds, {@code false} otherwise
745     */
746    public boolean removeAllNetworks() {
747        return mSupplicantStaIfaceHal.removeAllNetworks();
748    }
749
750    /**
751     * Set the BSSID for the currently configured network in wpa_supplicant.
752     *
753     * @return true if successful, false otherwise.
754     */
755    public boolean setConfiguredNetworkBSSID(String bssid) {
756        return mSupplicantStaIfaceHal.setCurrentNetworkBssid(bssid);
757    }
758
759    /**
760     * Initiate ANQP query.
761     *
762     * @param bssid BSSID of the AP to be queried
763     * @param anqpIds Set of anqp IDs.
764     * @param hs20Subtypes Set of HS20 subtypes.
765     * @return true on success, false otherwise.
766     */
767    public boolean requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes) {
768        if (bssid == null || ((anqpIds == null || anqpIds.isEmpty())
769                && (hs20Subtypes == null || hs20Subtypes.isEmpty()))) {
770            Log.e(mTAG, "Invalid arguments for ANQP request.");
771            return false;
772        }
773        ArrayList<Short> anqpIdList = new ArrayList<>();
774        for (Integer anqpId : anqpIds) {
775            anqpIdList.add(anqpId.shortValue());
776        }
777        ArrayList<Integer> hs20SubtypeList = new ArrayList<>();
778        hs20SubtypeList.addAll(hs20Subtypes);
779        return mSupplicantStaIfaceHal.initiateAnqpQuery(bssid, anqpIdList, hs20SubtypeList);
780    }
781
782    /**
783     * Request a passpoint icon file |filename| from the specified AP |bssid|.
784     * @param bssid BSSID of the AP
785     * @param fileName name of the icon file
786     * @return true if request is sent successfully, false otherwise
787     */
788    public boolean requestIcon(String  bssid, String fileName) {
789        if (bssid == null || fileName == null) {
790            Log.e(mTAG, "Invalid arguments for Icon request.");
791            return false;
792        }
793        return mSupplicantStaIfaceHal.initiateHs20IconQuery(bssid, fileName);
794    }
795
796    /**
797     * Get the currently configured network's WPS NFC token.
798     *
799     * @return Hex string corresponding to the WPS NFC token.
800     */
801    public String getNfcWpsConfigurationToken(int netId) {
802        return mSupplicantStaIfaceHal.getCurrentNetworkWpsNfcConfigurationToken();
803    }
804
805    /**
806     * Populate list of available networks or update existing list.
807     *
808     * @return true, if list has been modified.
809     */
810    public boolean p2pListNetworks(WifiP2pGroupList groups) {
811        return mSupplicantP2pIfaceHal.loadGroups(groups);
812    }
813
814    /**
815     * Initiate WPS Push Button setup.
816     * The PBC operation requires that a button is also pressed at the
817     * AP/Registrar at about the same time (2 minute window).
818     *
819     * @param iface Group interface name to use.
820     * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard.
821     * @return true, if operation was successful.
822     */
823    public boolean startWpsPbc(String iface, String bssid) {
824        return mSupplicantP2pIfaceHal.startWpsPbc(iface, bssid);
825    }
826
827    /**
828     * Initiate WPS Pin Keypad setup.
829     *
830     * @param iface Group interface name to use.
831     * @param pin 8 digit pin to be used.
832     * @return true, if operation was successful.
833     */
834    public boolean startWpsPinKeypad(String iface, String pin) {
835        return mSupplicantP2pIfaceHal.startWpsPinKeypad(iface, pin);
836    }
837
838    /**
839     * Initiate WPS Pin Display setup.
840     *
841     * @param iface Group interface name to use.
842     * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard.
843     * @return generated pin if operation was successful, null otherwise.
844     */
845    public String startWpsPinDisplay(String iface, String bssid) {
846        return mSupplicantP2pIfaceHal.startWpsPinDisplay(iface, bssid);
847    }
848
849    /**
850     * Remove network with provided id.
851     *
852     * @param netId Id of the network to lookup.
853     * @return true, if operation was successful.
854     */
855    public boolean removeP2pNetwork(int netId) {
856        return mSupplicantP2pIfaceHal.removeNetwork(netId);
857    }
858
859    /**
860     * Set WPS device name.
861     *
862     * @param name String to be set.
863     * @return true if request is sent successfully, false otherwise.
864     */
865    public boolean setP2pDeviceName(String name) {
866        return mSupplicantP2pIfaceHal.setWpsDeviceName(name);
867    }
868
869    /**
870     * Set WPS device type.
871     *
872     * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg>
873     * @return true if request is sent successfully, false otherwise.
874     */
875    public boolean setP2pDeviceType(String type) {
876        return mSupplicantP2pIfaceHal.setWpsDeviceType(type);
877    }
878
879    /**
880     * Set the postfix to be used for P2P SSID's.
881     *
882     * @param postfix String to be appended to SSID.
883     *
884     * @return boolean value indicating whether operation was successful.
885     */
886    public boolean setP2pSsidPostfix(String postfix) {
887        return mSupplicantP2pIfaceHal.setSsidPostfix(postfix);
888    }
889
890    /**
891     * Set the Maximum idle time in seconds for P2P groups.
892     * This value controls how long a P2P group is maintained after there
893     * is no other members in the group. As a group owner, this means no
894     * associated stations in the group. As a P2P client, this means no
895     * group owner seen in scan results.
896     *
897     * @param iface Group interface name to use.
898     * @param time Timeout value in seconds.
899     *
900     * @return boolean value indicating whether operation was successful.
901     */
902    public boolean setP2pGroupIdle(String iface, int time) {
903        return mSupplicantP2pIfaceHal.setGroupIdle(iface, time);
904    }
905
906    /**
907     * Turn on/off power save mode for the interface.
908     *
909     * @param iface Group interface name to use.
910     * @param enabled Indicate if power save is to be turned on/off.
911     *
912     * @return boolean value indicating whether operation was successful.
913     */
914    public boolean setP2pPowerSave(String iface, boolean enabled) {
915        return mSupplicantP2pIfaceHal.setPowerSave(iface, enabled);
916    }
917
918    /**
919     * Enable/Disable Wifi Display.
920     *
921     * @param enable true to enable, false to disable.
922     * @return true, if operation was successful.
923     */
924    public boolean setWfdEnable(boolean enable) {
925        return mSupplicantP2pIfaceHal.enableWfd(enable);
926    }
927
928    /**
929     * Set Wifi Display device info.
930     *
931     * @param hex WFD device info as described in section 5.1.2 of WFD technical
932     *        specification v1.0.0.
933     * @return true, if operation was successful.
934     */
935    public boolean setWfdDeviceInfo(String hex) {
936        return mSupplicantP2pIfaceHal.setWfdDeviceInfo(hex);
937    }
938
939    /**
940     * Initiate a P2P service discovery indefinitely.
941     *
942     * @return boolean value indicating whether operation was successful.
943     */
944    public boolean p2pFind() {
945        return p2pFind(0);
946    }
947
948    /**
949     * Initiate a P2P service discovery with a (optional) timeout.
950     *
951     * @param timeout Max time to be spent is peforming discovery.
952     *        Set to 0 to indefinely continue discovery untill and explicit
953     *        |stopFind| is sent.
954     * @return boolean value indicating whether operation was successful.
955     */
956    public boolean p2pFind(int timeout) {
957        return mSupplicantP2pIfaceHal.find(timeout);
958    }
959
960    /**
961     * Stop an ongoing P2P service discovery.
962     *
963     * @return boolean value indicating whether operation was successful.
964     */
965    public boolean p2pStopFind() {
966        return mSupplicantP2pIfaceHal.stopFind();
967    }
968
969    /**
970     * Configure Extended Listen Timing.
971     *
972     * If enabled, listen state must be entered every |intervalInMillis| for at
973     * least |periodInMillis|. Both values have acceptable range of 1-65535
974     * (with interval obviously having to be larger than or equal to duration).
975     * If the P2P module is not idle at the time the Extended Listen Timing
976     * timeout occurs, the Listen State operation must be skipped.
977     *
978     * @param enable Enables or disables listening.
979     * @param period Period in milliseconds.
980     * @param interval Interval in milliseconds.
981     *
982     * @return true, if operation was successful.
983     */
984    public boolean p2pExtListen(boolean enable, int period, int interval) {
985        return mSupplicantP2pIfaceHal.configureExtListen(enable, period, interval);
986    }
987
988    /**
989     * Set P2P Listen channel.
990     *
991     * When specifying a social channel on the 2.4 GHz band (1/6/11) there is no
992     * need to specify the operating class since it defaults to 81. When
993     * specifying a social channel on the 60 GHz band (2), specify the 60 GHz
994     * operating class (180).
995     *
996     * @param lc Wifi channel. eg, 1, 6, 11.
997     * @param oc Operating Class indicates the channel set of the AP
998     *        indicated by this BSSID
999     *
1000     * @return true, if operation was successful.
1001     */
1002    public boolean p2pSetChannel(int lc, int oc) {
1003        return mSupplicantP2pIfaceHal.setListenChannel(lc, oc);
1004    }
1005
1006    /**
1007     * Flush P2P peer table and state.
1008     *
1009     * @return boolean value indicating whether operation was successful.
1010     */
1011    public boolean p2pFlush() {
1012        return mSupplicantP2pIfaceHal.flush();
1013    }
1014
1015    /**
1016     * Start P2P group formation with a discovered P2P peer. This includes
1017     * optional group owner negotiation, group interface setup, provisioning,
1018     * and establishing data connection.
1019     *
1020     * @param config Configuration to use to connect to remote device.
1021     * @param joinExistingGroup Indicates that this is a command to join an
1022     *        existing group as a client. It skips the group owner negotiation
1023     *        part. This must send a Provision Discovery Request message to the
1024     *        target group owner before associating for WPS provisioning.
1025     *
1026     * @return String containing generated pin, if selected provision method
1027     *        uses PIN.
1028     */
1029    public String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) {
1030        return mSupplicantP2pIfaceHal.connect(config, joinExistingGroup);
1031    }
1032
1033    /**
1034     * Cancel an ongoing P2P group formation and joining-a-group related
1035     * operation. This operation unauthorizes the specific peer device (if any
1036     * had been authorized to start group formation), stops P2P find (if in
1037     * progress), stops pending operations for join-a-group, and removes the
1038     * P2P group interface (if one was used) that is in the WPS provisioning
1039     * step. If the WPS provisioning step has been completed, the group is not
1040     * terminated.
1041     *
1042     * @return boolean value indicating whether operation was successful.
1043     */
1044    public boolean p2pCancelConnect() {
1045        return mSupplicantP2pIfaceHal.cancelConnect();
1046    }
1047
1048    /**
1049     * Send P2P provision discovery request to the specified peer. The
1050     * parameters for this command are the P2P device address of the peer and the
1051     * desired configuration method.
1052     *
1053     * @param config Config class describing peer setup.
1054     *
1055     * @return boolean value indicating whether operation was successful.
1056     */
1057    public boolean p2pProvisionDiscovery(WifiP2pConfig config) {
1058        return mSupplicantP2pIfaceHal.provisionDiscovery(config);
1059    }
1060
1061    /**
1062     * Set up a P2P group owner manually.
1063     * This is a helper method that invokes groupAdd(networkId, isPersistent) internally.
1064     *
1065     * @param persistent Used to request a persistent group to be formed.
1066     *
1067     * @return true, if operation was successful.
1068     */
1069    public boolean p2pGroupAdd(boolean persistent) {
1070        return mSupplicantP2pIfaceHal.groupAdd(persistent);
1071    }
1072
1073    /**
1074     * Set up a P2P group owner manually (i.e., without group owner
1075     * negotiation with a specific peer). This is also known as autonomous
1076     * group owner.
1077     *
1078     * @param netId Used to specify the restart of a persistent group.
1079     *
1080     * @return true, if operation was successful.
1081     */
1082    public boolean p2pGroupAdd(int netId) {
1083        return mSupplicantP2pIfaceHal.groupAdd(netId, true);
1084    }
1085
1086    /**
1087     * Terminate a P2P group. If a new virtual network interface was used for
1088     * the group, it must also be removed. The network interface name of the
1089     * group interface is used as a parameter for this command.
1090     *
1091     * @param iface Group interface name to use.
1092     * @return true, if operation was successful.
1093     */
1094    public boolean p2pGroupRemove(String iface) {
1095        return mSupplicantP2pIfaceHal.groupRemove(iface);
1096    }
1097
1098    /**
1099     * Reject connection attempt from a peer (specified with a device
1100     * address). This is a mechanism to reject a pending group owner negotiation
1101     * with a peer and request to automatically block any further connection or
1102     * discovery of the peer.
1103     *
1104     * @param deviceAddress MAC address of the device to reject.
1105     *
1106     * @return boolean value indicating whether operation was successful.
1107     */
1108    public boolean p2pReject(String deviceAddress) {
1109        return mSupplicantP2pIfaceHal.reject(deviceAddress);
1110    }
1111
1112    /**
1113     * Invite a device to a persistent group.
1114     * If the peer device is the group owner of the persistent group, the peer
1115     * parameter is not needed. Otherwise it is used to specify which
1116     * device to invite. |goDeviceAddress| parameter may be used to override
1117     * the group owner device address for Invitation Request should it not be
1118     * known for some reason (this should not be needed in most cases).
1119     *
1120     * @param group Group object to use.
1121     * @param deviceAddress MAC address of the device to invite.
1122     *
1123     * @return boolean value indicating whether operation was successful.
1124     */
1125    public boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
1126        return mSupplicantP2pIfaceHal.invite(group, deviceAddress);
1127    }
1128
1129    /**
1130     * Reinvoke a device from a persistent group.
1131     *
1132     * @param netId Used to specify the persistent group.
1133     * @param deviceAddress MAC address of the device to reinvoke.
1134     *
1135     * @return true, if operation was successful.
1136     */
1137    public boolean p2pReinvoke(int netId, String deviceAddress) {
1138        return mSupplicantP2pIfaceHal.reinvoke(netId, deviceAddress);
1139    }
1140
1141    /**
1142     * Gets the operational SSID of the device.
1143     *
1144     * @param deviceAddress MAC address of the peer.
1145     *
1146     * @return SSID of the device.
1147     */
1148    public String p2pGetSsid(String deviceAddress) {
1149        return mSupplicantP2pIfaceHal.getSsid(deviceAddress);
1150    }
1151
1152    /**
1153     * Gets the MAC address of the device.
1154     *
1155     * @return MAC address of the device.
1156     */
1157    public String p2pGetDeviceAddress() {
1158        return mSupplicantP2pIfaceHal.getDeviceAddress();
1159    }
1160
1161    /**
1162     * Gets the capability of the group which the device is a
1163     * member of.
1164     *
1165     * @param deviceAddress MAC address of the peer.
1166     *
1167     * @return combination of |GroupCapabilityMask| values.
1168     */
1169    public int getGroupCapability(String deviceAddress) {
1170        return mSupplicantP2pIfaceHal.getGroupCapability(deviceAddress);
1171    }
1172
1173    /**
1174     * This command can be used to add a upnp/bonjour service.
1175     *
1176     * @param servInfo List of service queries.
1177     *
1178     * @return true, if operation was successful.
1179     */
1180    public boolean p2pServiceAdd(WifiP2pServiceInfo servInfo) {
1181        return mSupplicantP2pIfaceHal.serviceAdd(servInfo);
1182    }
1183
1184    /**
1185     * This command can be used to remove a upnp/bonjour service.
1186     *
1187     * @param servInfo List of service queries.
1188     *
1189     * @return true, if operation was successful.
1190     */
1191    public boolean p2pServiceDel(WifiP2pServiceInfo servInfo) {
1192        return mSupplicantP2pIfaceHal.serviceRemove(servInfo);
1193    }
1194
1195    /**
1196     * This command can be used to flush all services from the
1197     * device.
1198     *
1199     * @return boolean value indicating whether operation was successful.
1200     */
1201    public boolean p2pServiceFlush() {
1202        return mSupplicantP2pIfaceHal.serviceFlush();
1203    }
1204
1205    /**
1206     * Schedule a P2P service discovery request. The parameters for this command
1207     * are the device address of the peer device (or 00:00:00:00:00:00 for
1208     * wildcard query that is sent to every discovered P2P peer that supports
1209     * service discovery) and P2P Service Query TLV(s) as hexdump.
1210     *
1211     * @param addr MAC address of the device to discover.
1212     * @param query Hex dump of the query data.
1213     * @return identifier Identifier for the request. Can be used to cancel the
1214     *         request.
1215     */
1216    public String p2pServDiscReq(String addr, String query) {
1217        return mSupplicantP2pIfaceHal.requestServiceDiscovery(addr, query);
1218    }
1219
1220    /**
1221     * Cancel a previous service discovery request.
1222     *
1223     * @param id Identifier for the request to cancel.
1224     * @return true, if operation was successful.
1225     */
1226    public boolean p2pServDiscCancelReq(String id) {
1227        return mSupplicantP2pIfaceHal.cancelServiceDiscovery(id);
1228    }
1229
1230    /**
1231     * Send driver command to set Miracast mode.
1232     *
1233     * @param mode Mode of Miracast.
1234     *        0 = disabled
1235     *        1 = operating as source
1236     *        2 = operating as sink
1237     */
1238    public void setMiracastMode(int mode) {
1239        mSupplicantP2pIfaceHal.setMiracastMode(mode);
1240    }
1241
1242    /**
1243     * Get NFC handover request message.
1244     *
1245     * @return select message if created successfully, null otherwise.
1246     */
1247    public String getNfcHandoverRequest() {
1248        return mSupplicantP2pIfaceHal.getNfcHandoverRequest();
1249    }
1250
1251    /**
1252     * Get NFC handover select message.
1253     *
1254     * @return select message if created successfully, null otherwise.
1255     */
1256    public String getNfcHandoverSelect() {
1257        return mSupplicantP2pIfaceHal.getNfcHandoverSelect();
1258    }
1259
1260    /**
1261     * Report NFC handover select message.
1262     *
1263     * @return true if reported successfully, false otherwise.
1264     */
1265    public boolean initiatorReportNfcHandover(String selectMessage) {
1266        return mSupplicantP2pIfaceHal.initiatorReportNfcHandover(selectMessage);
1267    }
1268
1269    /**
1270     * Report NFC handover request message.
1271     *
1272     * @return true if reported successfully, false otherwise.
1273     */
1274    public boolean responderReportNfcHandover(String requestMessage) {
1275        return mSupplicantP2pIfaceHal.responderReportNfcHandover(requestMessage);
1276    }
1277
1278    /**
1279     * Get P2P client list for the given network ID.
1280     * @return true on success, false otherwise.
1281     */
1282    public String getP2pClientList(int netId) {
1283        // TODO(b/36042785): Add HIDL method.
1284        return null;
1285    }
1286
1287    /**
1288     * Set P2P client list for the given network ID.
1289     * @return true on success, false otherwise.
1290     */
1291    public boolean setP2pClientList(int netId, String list) {
1292        // TODO(b/36042785): Add HIDL method.
1293        return false;
1294    }
1295
1296    /**
1297     * Save the current configuration to wpa_supplicant.conf.
1298     */
1299    public boolean saveConfig() {
1300        // TODO(b/36042785): Add HIDL method.
1301        return false;
1302    }
1303
1304    /********************************************************
1305     * Vendor HAL operations
1306     ********************************************************/
1307
1308    /**
1309     * Initializes the vendor HAL. This is just used to initialize the {@link HalDeviceManager}.
1310     */
1311    public boolean initializeVendorHal() {
1312        return mWifiVendorHal.initialize();
1313    }
1314
1315    /**
1316     * Bring up the Vendor HAL and configure for STA mode or AP mode.
1317     *
1318     * @param isStaMode true to start HAL in STA mode, false to start in AP mode.
1319     */
1320    public boolean startHal(boolean isStaMode) {
1321        return mWifiVendorHal.startVendorHal(isStaMode);
1322    }
1323
1324    /**
1325     * Stops the HAL
1326     */
1327    public void stopHal() {
1328        mWifiVendorHal.stopVendorHal();
1329    }
1330
1331    /**
1332     * Tests whether the HAL is running or not
1333     */
1334    public boolean isHalStarted() {
1335        return mWifiVendorHal.isHalStarted();
1336    }
1337
1338    // TODO: Change variable names to camel style.
1339    public static class ScanCapabilities {
1340        public int  max_scan_cache_size;
1341        public int  max_scan_buckets;
1342        public int  max_ap_cache_per_scan;
1343        public int  max_rssi_sample_size;
1344        public int  max_scan_reporting_threshold;
1345        public int  max_hotlist_bssids;
1346        public int  max_significant_wifi_change_aps;
1347        public int  max_bssid_history_entries;
1348        public int  max_number_epno_networks;
1349        public int  max_number_epno_networks_by_ssid;
1350        public int  max_number_of_white_listed_ssid;
1351    }
1352
1353    /**
1354     * Gets the scan capabilities
1355     *
1356     * @param capabilities object to be filled in
1357     * @return true for success. false for failure
1358     */
1359    public boolean getBgScanCapabilities(ScanCapabilities capabilities) {
1360        return mWifiVendorHal.getBgScanCapabilities(capabilities);
1361    }
1362
1363    public static class ChannelSettings {
1364        public int frequency;
1365        public int dwell_time_ms;
1366        public boolean passive;
1367    }
1368
1369    public static class BucketSettings {
1370        public int bucket;
1371        public int band;
1372        public int period_ms;
1373        public int max_period_ms;
1374        public int step_count;
1375        public int report_events;
1376        public int num_channels;
1377        public ChannelSettings[] channels;
1378    }
1379
1380    /**
1381     * Network parameters for hidden networks to be scanned for.
1382     */
1383    public static class HiddenNetwork {
1384        public String ssid;
1385
1386        @Override
1387        public boolean equals(Object otherObj) {
1388            if (this == otherObj) {
1389                return true;
1390            } else if (otherObj == null || getClass() != otherObj.getClass()) {
1391                return false;
1392            }
1393            HiddenNetwork other = (HiddenNetwork) otherObj;
1394            return Objects.equals(ssid, other.ssid);
1395        }
1396
1397        @Override
1398        public int hashCode() {
1399            return (ssid == null ? 0 : ssid.hashCode());
1400        }
1401    }
1402
1403    public static class ScanSettings {
1404        public int base_period_ms;
1405        public int max_ap_per_scan;
1406        public int report_threshold_percent;
1407        public int report_threshold_num_scans;
1408        public int num_buckets;
1409        /* Not used for bg scans. Only works for single scans. */
1410        public HiddenNetwork[] hiddenNetworks;
1411        public BucketSettings[] buckets;
1412    }
1413
1414    /**
1415     * Network parameters to start PNO scan.
1416     */
1417    public static class PnoNetwork {
1418        public String ssid;
1419        public byte flags;
1420        public byte auth_bit_field;
1421
1422        @Override
1423        public boolean equals(Object otherObj) {
1424            if (this == otherObj) {
1425                return true;
1426            } else if (otherObj == null || getClass() != otherObj.getClass()) {
1427                return false;
1428            }
1429            PnoNetwork other = (PnoNetwork) otherObj;
1430            return ((Objects.equals(ssid, other.ssid)) && (flags == other.flags)
1431                    && (auth_bit_field == other.auth_bit_field));
1432        }
1433
1434        @Override
1435        public int hashCode() {
1436            int result = (ssid == null ? 0 : ssid.hashCode());
1437            result ^= ((int) flags * 31) + ((int) auth_bit_field << 8);
1438            return result;
1439        }
1440    }
1441
1442    /**
1443     * Parameters to start PNO scan. This holds the list of networks which are going to used for
1444     * PNO scan.
1445     */
1446    public static class PnoSettings {
1447        public int min5GHzRssi;
1448        public int min24GHzRssi;
1449        public int initialScoreMax;
1450        public int currentConnectionBonus;
1451        public int sameNetworkBonus;
1452        public int secureBonus;
1453        public int band5GHzBonus;
1454        public int periodInMs;
1455        public boolean isConnected;
1456        public PnoNetwork[] networkList;
1457    }
1458
1459    public static interface ScanEventHandler {
1460        /**
1461         * Called for each AP as it is found with the entire contents of the beacon/probe response.
1462         * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified.
1463         */
1464        void onFullScanResult(ScanResult fullScanResult, int bucketsScanned);
1465        /**
1466         * Callback on an event during a gscan scan.
1467         * See WifiNative.WIFI_SCAN_* for possible values.
1468         */
1469        void onScanStatus(int event);
1470        /**
1471         * Called with the current cached scan results when gscan is paused.
1472         */
1473        void onScanPaused(WifiScanner.ScanData[] data);
1474        /**
1475         * Called with the current cached scan results when gscan is resumed.
1476         */
1477        void onScanRestarted();
1478    }
1479
1480    /**
1481     * Handler to notify the occurrence of various events during PNO scan.
1482     */
1483    public interface PnoEventHandler {
1484        /**
1485         * Callback to notify when one of the shortlisted networks is found during PNO scan.
1486         * @param results List of Scan results received.
1487         */
1488        void onPnoNetworkFound(ScanResult[] results);
1489
1490        /**
1491         * Callback to notify when the PNO scan schedule fails.
1492         */
1493        void onPnoScanFailed();
1494    }
1495
1496    public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0;
1497    public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1;
1498    public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2;
1499    public static final int WIFI_SCAN_FAILED = 3;
1500
1501    /**
1502     * Starts a background scan.
1503     * Any ongoing scan will be stopped first
1504     *
1505     * @param settings     to control the scan
1506     * @param eventHandler to call with the results
1507     * @return true for success
1508     */
1509    public boolean startBgScan(ScanSettings settings, ScanEventHandler eventHandler) {
1510        return mWifiVendorHal.startBgScan(settings, eventHandler);
1511    }
1512
1513    /**
1514     * Stops any ongoing backgound scan
1515     */
1516    public void stopBgScan() {
1517        mWifiVendorHal.stopBgScan();
1518    }
1519
1520    /**
1521     * Pauses an ongoing backgound scan
1522     */
1523    public void pauseBgScan() {
1524        mWifiVendorHal.pauseBgScan();
1525    }
1526
1527    /**
1528     * Restarts a paused scan
1529     */
1530    public void restartBgScan() {
1531        mWifiVendorHal.restartBgScan();
1532    }
1533
1534    /**
1535     * Gets the latest scan results received.
1536     */
1537    public WifiScanner.ScanData[] getBgScanResults() {
1538        return mWifiVendorHal.getBgScanResults();
1539    }
1540
1541    public static interface HotlistEventHandler {
1542        void onHotlistApFound (ScanResult[] result);
1543        void onHotlistApLost  (ScanResult[] result);
1544    }
1545
1546    public boolean setHotlist(WifiScanner.HotlistSettings settings,
1547            HotlistEventHandler eventHandler) {
1548        Log.e(mTAG, "setHotlist not supported");
1549        return false;
1550    }
1551
1552    public void resetHotlist() {
1553        Log.e(mTAG, "resetHotlist not supported");
1554    }
1555
1556    public static interface SignificantWifiChangeEventHandler {
1557        void onChangesFound(ScanResult[] result);
1558    }
1559
1560    public boolean trackSignificantWifiChange(
1561            WifiScanner.WifiChangeSettings settings, SignificantWifiChangeEventHandler handler) {
1562        Log.e(mTAG, "trackSignificantWifiChange not supported");
1563        return false;
1564    }
1565
1566    public void untrackSignificantWifiChange() {
1567        Log.e(mTAG, "untrackSignificantWifiChange not supported");
1568    }
1569
1570    public WifiLinkLayerStats getWifiLinkLayerStats(String iface) {
1571        return mWifiVendorHal.getWifiLinkLayerStats();
1572    }
1573
1574    public void setWifiLinkLayerStats(String iface, int enable) {
1575        // TODO(b//36087365) Remove this. Link layer stats is enabled when the HAL is started.
1576    }
1577
1578    /**
1579     * Get the supported features
1580     *
1581     * @return bitmask defined by WifiManager.WIFI_FEATURE_*
1582     */
1583    public int getSupportedFeatureSet() {
1584        return mWifiVendorHal.getSupportedFeatureSet();
1585    }
1586
1587    public static interface RttEventHandler {
1588        void onRttResults(RttManager.RttResult[] result);
1589    }
1590
1591    /**
1592     * Starts a new rtt request
1593     *
1594     * @param params RTT request params. Refer to {@link RttManager#RttParams}.
1595     * @param handler Callback to be invoked to notify any results.
1596     * @return true if the request was successful, false otherwise.
1597     */
1598    public boolean requestRtt(
1599            RttManager.RttParams[] params, RttEventHandler handler) {
1600        return mWifiVendorHal.requestRtt(params, handler);
1601    }
1602
1603    /**
1604     * Cancels an outstanding rtt request
1605     *
1606     * @param params RTT request params. Refer to {@link RttManager#RttParams}
1607     * @return true if there was an outstanding request and it was successfully cancelled
1608     */
1609    public boolean cancelRtt(RttManager.RttParams[] params) {
1610        return mWifiVendorHal.cancelRtt(params);
1611    }
1612
1613    /**
1614     * Enable RTT responder role on the device. Returns {@link ResponderConfig} if the responder
1615     * role is successfully enabled, {@code null} otherwise.
1616     *
1617     * @param timeoutSeconds timeout to use for the responder.
1618     */
1619    @Nullable
1620    public ResponderConfig enableRttResponder(int timeoutSeconds) {
1621        return mWifiVendorHal.enableRttResponder(timeoutSeconds);
1622    }
1623
1624    /**
1625     * Disable RTT responder role. Returns {@code true} if responder role is successfully disabled,
1626     * {@code false} otherwise.
1627     */
1628    public boolean disableRttResponder() {
1629        return mWifiVendorHal.disableRttResponder();
1630    }
1631
1632    /**
1633     * Set the MAC OUI during scanning.
1634     * An OUI {Organizationally Unique Identifier} is a 24-bit number that
1635     * uniquely identifies a vendor or manufacturer.
1636     *
1637     * @param oui OUI to set.
1638     * @return true for success
1639     */
1640    public boolean setScanningMacOui(byte[] oui) {
1641        return mWifiVendorHal.setScanningMacOui(oui);
1642    }
1643
1644    /**
1645     * Query the list of valid frequencies for the provided band.
1646     * The result depends on the on the country code that has been set.
1647     *
1648     * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
1649     * @return frequencies vector of valid frequencies (MHz), or null for error.
1650     * @throws IllegalArgumentException if band is not recognized.
1651     */
1652    public int [] getChannelsForBand(int band) {
1653        return mWifiVendorHal.getChannelsForBand(band);
1654    }
1655
1656    /**
1657     * Indicates whether getChannelsForBand is supported.
1658     *
1659     * @return true if it is.
1660     */
1661    public boolean isGetChannelsForBandSupported() {
1662        return mWifiVendorHal.isGetChannelsForBandSupported();
1663    }
1664
1665    /**
1666     * Set DFS - actually, this is always on.
1667     *
1668     * @param dfsOn
1669     * @return success indication
1670     */
1671    public boolean setDfsFlag(boolean dfsOn) {
1672        return mWifiVendorHal.setDfsFlag(dfsOn);
1673    }
1674
1675    /**
1676     * RTT (Round Trip Time) measurement capabilities of the device.
1677     */
1678    public RttManager.RttCapabilities getRttCapabilities() {
1679        return mWifiVendorHal.getRttCapabilities();
1680    }
1681
1682    /**
1683     * Get the APF (Android Packet Filter) capabilities of the device
1684     */
1685    public ApfCapabilities getApfCapabilities() {
1686        return mWifiVendorHal.getApfCapabilities();
1687    }
1688
1689    /**
1690     * Installs an APF program on this iface, replacing any existing program.
1691     *
1692     * @param filter is the android packet filter program
1693     * @return true for success
1694     */
1695    public boolean installPacketFilter(byte[] filter) {
1696        return mWifiVendorHal.installPacketFilter(filter);
1697    }
1698
1699    /**
1700     * Set country code for this AP iface.
1701     *
1702     * @param countryCode - two-letter country code (as ISO 3166)
1703     * @return true for success
1704     */
1705    public boolean setCountryCodeHal(String countryCode) {
1706        return mWifiVendorHal.setCountryCodeHal(countryCode);
1707    }
1708
1709    //---------------------------------------------------------------------------------
1710    /* Wifi Logger commands/events */
1711    public static interface WifiLoggerEventHandler {
1712        void onRingBufferData(RingBufferStatus status, byte[] buffer);
1713        void onWifiAlert(int errorCode, byte[] buffer);
1714    }
1715
1716    /**
1717     * Registers the logger callback and enables alerts.
1718     * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked.
1719     *
1720     * @param handler Callback to be invoked.
1721     * @return true on success, false otherwise.
1722     */
1723    public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) {
1724        return mWifiVendorHal.setLoggingEventHandler(handler);
1725    }
1726
1727    /**
1728     * Control debug data collection
1729     *
1730     * @param verboseLevel 0 to 3, inclusive. 0 stops logging.
1731     * @param flags        Ignored.
1732     * @param maxInterval  Maximum interval between reports; ignore if 0.
1733     * @param minDataSize  Minimum data size in buffer for report; ignore if 0.
1734     * @param ringName     Name of the ring for which data collection is to start.
1735     * @return true for success, false otherwise.
1736     */
1737    public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval,
1738            int minDataSize, String ringName){
1739        return mWifiVendorHal.startLoggingRingBuffer(
1740                verboseLevel, flags, maxInterval, minDataSize, ringName);
1741    }
1742
1743    /**
1744     * Logger features exposed.
1745     * This is a no-op now, will always return -1.
1746     *
1747     * @return true on success, false otherwise.
1748     */
1749    public int getSupportedLoggerFeatureSet() {
1750        return mWifiVendorHal.getSupportedLoggerFeatureSet();
1751    }
1752
1753    /**
1754     * Stops all logging and resets the logger callback.
1755     * This stops both the alerts and ring buffer data collection.
1756     * @return true on success, false otherwise.
1757     */
1758    public boolean resetLogHandler() {
1759        return mWifiVendorHal.resetLogHandler();
1760    }
1761
1762    /**
1763     * Vendor-provided wifi driver version string
1764     *
1765     * @return String returned from the HAL.
1766     */
1767    public String getDriverVersion() {
1768        return mWifiVendorHal.getDriverVersion();
1769    }
1770
1771    /**
1772     * Vendor-provided wifi firmware version string
1773     *
1774     * @return String returned from the HAL.
1775     */
1776    public String getFirmwareVersion() {
1777        return mWifiVendorHal.getFirmwareVersion();
1778    }
1779
1780    public static class RingBufferStatus{
1781        String name;
1782        int flag;
1783        int ringBufferId;
1784        int ringBufferByteSize;
1785        int verboseLevel;
1786        int writtenBytes;
1787        int readBytes;
1788        int writtenRecords;
1789
1790        // Bit masks for interpreting |flag|
1791        public static final int HAS_BINARY_ENTRIES = (1 << 0);
1792        public static final int HAS_ASCII_ENTRIES = (1 << 1);
1793        public static final int HAS_PER_PACKET_ENTRIES = (1 << 2);
1794
1795        @Override
1796        public String toString() {
1797            return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId +
1798                    " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel +
1799                    " writtenBytes: " + writtenBytes + " readBytes: " + readBytes +
1800                    " writtenRecords: " + writtenRecords;
1801        }
1802    }
1803
1804    /**
1805     * API to get the status of all ring buffers supported by driver
1806     */
1807    public RingBufferStatus[] getRingBufferStatus() {
1808        return mWifiVendorHal.getRingBufferStatus();
1809    }
1810
1811    /**
1812     * Indicates to driver that all the data has to be uploaded urgently
1813     *
1814     * @param ringName Name of the ring buffer requested.
1815     * @return true on success, false otherwise.
1816     */
1817    public boolean getRingBufferData(String ringName) {
1818        return mWifiVendorHal.getRingBufferData(ringName);
1819    }
1820
1821    /**
1822     * Request vendor debug info from the firmware
1823     *
1824     * @return Raw data obtained from the HAL.
1825     */
1826    public byte[] getFwMemoryDump() {
1827        return mWifiVendorHal.getFwMemoryDump();
1828    }
1829
1830    /**
1831     * Request vendor debug info from the driver
1832     *
1833     * @return Raw data obtained from the HAL.
1834     */
1835    public byte[] getDriverStateDump() {
1836        return mWifiVendorHal.getDriverStateDump();
1837    }
1838
1839    //---------------------------------------------------------------------------------
1840    /* Packet fate API */
1841
1842    @Immutable
1843    abstract static class FateReport {
1844        final static int USEC_PER_MSEC = 1000;
1845        // The driver timestamp is a 32-bit counter, in microseconds. This field holds the
1846        // maximal value of a driver timestamp in milliseconds.
1847        final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000);
1848        final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS");
1849
1850        final byte mFate;
1851        final long mDriverTimestampUSec;
1852        final byte mFrameType;
1853        final byte[] mFrameBytes;
1854        final long mEstimatedWallclockMSec;
1855
1856        FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1857            mFate = fate;
1858            mDriverTimestampUSec = driverTimestampUSec;
1859            mEstimatedWallclockMSec =
1860                    convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec);
1861            mFrameType = frameType;
1862            mFrameBytes = frameBytes;
1863        }
1864
1865        public String toTableRowString() {
1866            StringWriter sw = new StringWriter();
1867            PrintWriter pw = new PrintWriter(sw);
1868            FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
1869            dateFormatter.setTimeZone(TimeZone.getDefault());
1870            pw.format("%-15s  %12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1871                    mDriverTimestampUSec,
1872                    dateFormatter.format(new Date(mEstimatedWallclockMSec)),
1873                    directionToString(), fateToString(), parser.mMostSpecificProtocolString,
1874                    parser.mTypeString, parser.mResultString);
1875            return sw.toString();
1876        }
1877
1878        public String toVerboseStringWithPiiAllowed() {
1879            StringWriter sw = new StringWriter();
1880            PrintWriter pw = new PrintWriter(sw);
1881            FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
1882            pw.format("Frame direction: %s\n", directionToString());
1883            pw.format("Frame timestamp: %d\n", mDriverTimestampUSec);
1884            pw.format("Frame fate: %s\n", fateToString());
1885            pw.format("Frame type: %s\n", frameTypeToString(mFrameType));
1886            pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString);
1887            pw.format("Frame protocol type: %s\n", parser.mTypeString);
1888            pw.format("Frame length: %d\n", mFrameBytes.length);
1889            pw.append("Frame bytes");
1890            pw.append(HexDump.dumpHexString(mFrameBytes));  // potentially contains PII
1891            pw.append("\n");
1892            return sw.toString();
1893        }
1894
1895        /* Returns a header to match the output of toTableRowString(). */
1896        public static String getTableHeader() {
1897            StringWriter sw = new StringWriter();
1898            PrintWriter pw = new PrintWriter(sw);
1899            pw.format("\n%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1900                    "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result");
1901            pw.format("%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
1902                    "---------", "--------", "---------", "----", "--------", "----", "------");
1903            return sw.toString();
1904        }
1905
1906        protected abstract String directionToString();
1907
1908        protected abstract String fateToString();
1909
1910        private static String frameTypeToString(byte frameType) {
1911            switch (frameType) {
1912                case WifiLoggerHal.FRAME_TYPE_UNKNOWN:
1913                    return "unknown";
1914                case WifiLoggerHal.FRAME_TYPE_ETHERNET_II:
1915                    return "data";
1916                case WifiLoggerHal.FRAME_TYPE_80211_MGMT:
1917                    return "802.11 management";
1918                default:
1919                    return Byte.toString(frameType);
1920            }
1921        }
1922
1923        /**
1924         * Converts a driver timestamp to a wallclock time, based on the current
1925         * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of
1926         * microseconds, with the same base as BOOTTIME.
1927         */
1928        private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) {
1929            final long wallclockMillisNow = System.currentTimeMillis();
1930            final long boottimeMillisNow = SystemClock.elapsedRealtime();
1931            final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC;
1932
1933            long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC;
1934            if (boottimeTimestampMillis < driverTimestampMillis) {
1935                // The 32-bit microsecond count has wrapped between the time that the driver
1936                // recorded the packet, and the call to this function. Adjust the BOOTTIME
1937                // timestamp, to compensate.
1938                //
1939                // Note that overflow is not a concern here, since the result is less than
1940                // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above,
1941                // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since
1942                // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit
1943                // within a long.
1944                boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC;
1945            }
1946
1947            final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis;
1948            return wallclockMillisNow - millisSincePacketTimestamp;
1949        }
1950    }
1951
1952    /**
1953     * Represents the fate information for one outbound packet.
1954     */
1955    @Immutable
1956    public static final class TxFateReport extends FateReport {
1957        TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1958            super(fate, driverTimestampUSec, frameType, frameBytes);
1959        }
1960
1961        @Override
1962        protected String directionToString() {
1963            return "TX";
1964        }
1965
1966        @Override
1967        protected String fateToString() {
1968            switch (mFate) {
1969                case WifiLoggerHal.TX_PKT_FATE_ACKED:
1970                    return "acked";
1971                case WifiLoggerHal.TX_PKT_FATE_SENT:
1972                    return "sent";
1973                case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED:
1974                    return "firmware queued";
1975                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID:
1976                    return "firmware dropped (invalid frame)";
1977                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS:
1978                    return "firmware dropped (no bufs)";
1979                case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER:
1980                    return "firmware dropped (other)";
1981                case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED:
1982                    return "driver queued";
1983                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID:
1984                    return "driver dropped (invalid frame)";
1985                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS:
1986                    return "driver dropped (no bufs)";
1987                case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER:
1988                    return "driver dropped (other)";
1989                default:
1990                    return Byte.toString(mFate);
1991            }
1992        }
1993    }
1994
1995    /**
1996     * Represents the fate information for one inbound packet.
1997     */
1998    @Immutable
1999    public static final class RxFateReport extends FateReport {
2000        RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
2001            super(fate, driverTimestampUSec, frameType, frameBytes);
2002        }
2003
2004        @Override
2005        protected String directionToString() {
2006            return "RX";
2007        }
2008
2009        @Override
2010        protected String fateToString() {
2011            switch (mFate) {
2012                case WifiLoggerHal.RX_PKT_FATE_SUCCESS:
2013                    return "success";
2014                case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED:
2015                    return "firmware queued";
2016                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER:
2017                    return "firmware dropped (filter)";
2018                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID:
2019                    return "firmware dropped (invalid frame)";
2020                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS:
2021                    return "firmware dropped (no bufs)";
2022                case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER:
2023                    return "firmware dropped (other)";
2024                case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED:
2025                    return "driver queued";
2026                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER:
2027                    return "driver dropped (filter)";
2028                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID:
2029                    return "driver dropped (invalid frame)";
2030                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS:
2031                    return "driver dropped (no bufs)";
2032                case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER:
2033                    return "driver dropped (other)";
2034                default:
2035                    return Byte.toString(mFate);
2036            }
2037        }
2038    }
2039
2040    /**
2041     * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started.
2042     *
2043     * @return true for success, false otherwise.
2044     */
2045    public boolean startPktFateMonitoring() {
2046        return mWifiVendorHal.startPktFateMonitoring();
2047    }
2048
2049    /**
2050     * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started.
2051     *
2052     * @return true for success, false otherwise.
2053     */
2054    public boolean getTxPktFates(TxFateReport[] reportBufs) {
2055        return mWifiVendorHal.getTxPktFates(reportBufs);
2056    }
2057
2058    /**
2059     * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started.
2060     */
2061    public boolean getRxPktFates(RxFateReport[] reportBufs) {
2062        return mWifiVendorHal.getRxPktFates(reportBufs);
2063    }
2064
2065    /**
2066     * Set the PNO settings & the network list in HAL to start PNO.
2067     * @param settings PNO settings and network list.
2068     * @param eventHandler Handler to receive notifications back during PNO scan.
2069     * @return true if success, false otherwise
2070     */
2071    public boolean setPnoList(PnoSettings settings, PnoEventHandler eventHandler) {
2072        Log.e(mTAG, "setPnoList not supported");
2073        return false;
2074    }
2075
2076    /**
2077     * Reset the PNO settings in HAL to stop PNO.
2078     * @return true if success, false otherwise
2079     */
2080    public boolean resetPnoList() {
2081        Log.e(mTAG, "resetPnoList not supported");
2082        return false;
2083    }
2084
2085    /**
2086     * Start sending the specified keep alive packets periodically.
2087     *
2088     * @param slot Integer used to identify each request.
2089     * @param keepAlivePacket Raw packet contents to send.
2090     * @param period Period to use for sending these packets.
2091     * @return 0 for success, -1 for error
2092     */
2093    public int startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket,
2094                                           int period) {
2095        String[] macAddrStr = getMacAddress().split(":");
2096        byte[] srcMac = new byte[6];
2097        for (int i = 0; i < 6; i++) {
2098            Integer hexVal = Integer.parseInt(macAddrStr[i], 16);
2099            srcMac[i] = hexVal.byteValue();
2100        }
2101        return mWifiVendorHal.startSendingOffloadedPacket(
2102                slot, srcMac, keepAlivePacket, period);
2103    }
2104
2105    /**
2106     * Stop sending the specified keep alive packets.
2107     *
2108     * @param slot id - same as startSendingOffloadedPacket call.
2109     * @return 0 for success, -1 for error
2110     */
2111    public int stopSendingOffloadedPacket(int slot) {
2112        return mWifiVendorHal.stopSendingOffloadedPacket(slot);
2113    }
2114
2115    public static interface WifiRssiEventHandler {
2116        void onRssiThresholdBreached(byte curRssi);
2117    }
2118
2119    /**
2120     * Start RSSI monitoring on the currently connected access point.
2121     *
2122     * @param maxRssi          Maximum RSSI threshold.
2123     * @param minRssi          Minimum RSSI threshold.
2124     * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi
2125     * @return 0 for success, -1 for failure
2126     */
2127    public int startRssiMonitoring(byte maxRssi, byte minRssi,
2128                                   WifiRssiEventHandler rssiEventHandler) {
2129        return mWifiVendorHal.startRssiMonitoring(maxRssi, minRssi, rssiEventHandler);
2130    }
2131
2132    public int stopRssiMonitoring() {
2133        return mWifiVendorHal.stopRssiMonitoring();
2134    }
2135
2136    /**
2137     * Fetch the host wakeup reasons stats from wlan driver.
2138     *
2139     * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver.
2140     */
2141    public WifiWakeReasonAndCounts getWlanWakeReasonCount() {
2142        return mWifiVendorHal.getWlanWakeReasonCount();
2143    }
2144
2145    /**
2146     * Enable/Disable Neighbour discovery offload functionality in the firmware.
2147     *
2148     * @param enabled true to enable, false to disable.
2149     * @return true for success, false otherwise.
2150     */
2151    public boolean configureNeighborDiscoveryOffload(boolean enabled) {
2152        return mWifiVendorHal.configureNeighborDiscoveryOffload(enabled);
2153    }
2154
2155    // Firmware roaming control.
2156
2157    /**
2158     * Class to retrieve firmware roaming capability parameters.
2159     */
2160    public static class RoamingCapabilities {
2161        public int  maxBlacklistSize;
2162        public int  maxWhitelistSize;
2163    }
2164
2165    /**
2166     * Query the firmware roaming capabilities.
2167     * @return true for success, false otherwise.
2168     */
2169    public boolean getRoamingCapabilities(RoamingCapabilities capabilities) {
2170        return mWifiVendorHal.getRoamingCapabilities(capabilities);
2171    }
2172
2173    /**
2174     * Macros for controlling firmware roaming.
2175     */
2176    public static final int DISABLE_FIRMWARE_ROAMING = 0;
2177    public static final int ENABLE_FIRMWARE_ROAMING = 1;
2178
2179    /**
2180     * Enable/disable firmware roaming.
2181     *
2182     * @return error code returned from HAL.
2183     */
2184    public int enableFirmwareRoaming(int state) {
2185        return mWifiVendorHal.enableFirmwareRoaming(state);
2186    }
2187
2188    /**
2189     * Class for specifying the roaming configurations.
2190     */
2191    public static class RoamingConfig {
2192        public ArrayList<String> blacklistBssids;
2193        public ArrayList<String> whitelistSsids;
2194    }
2195
2196    /**
2197     * Set firmware roaming configurations.
2198     */
2199    public boolean configureRoaming(RoamingConfig config) {
2200        Log.d(mTAG, "configureRoaming ");
2201        return mWifiVendorHal.configureRoaming(config);
2202    }
2203
2204    /**
2205     * Reset firmware roaming configuration.
2206     */
2207    public boolean resetRoamingConfiguration() {
2208        // Pass in an empty RoamingConfig object which translates to zero size
2209        // blacklist and whitelist to reset the firmware roaming configuration.
2210        return mWifiVendorHal.configureRoaming(new RoamingConfig());
2211    }
2212
2213    /********************************************************
2214     * JNI operations
2215     ********************************************************/
2216    /* Register native functions */
2217    static {
2218        /* Native functions are defined in libwifi-service.so */
2219        System.loadLibrary("wifi-service");
2220        registerNatives();
2221    }
2222
2223    private static native int registerNatives();
2224    /* kernel logging support */
2225    private static native byte[] readKernelLogNative();
2226
2227    /**
2228     * Fetches the latest kernel logs.
2229     */
2230    public synchronized String readKernelLog() {
2231        byte[] bytes = readKernelLogNative();
2232        if (bytes != null) {
2233            CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
2234            try {
2235                CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
2236                return decoded.toString();
2237            } catch (CharacterCodingException cce) {
2238                return new String(bytes, StandardCharsets.ISO_8859_1);
2239            }
2240        } else {
2241            return "*** failed to read kernel log ***";
2242        }
2243    }
2244}
2245