WifiNative.java revision 71c4c2a898a827a867564159ce78e41aedd2295b
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.os.SystemClock;
31import android.util.Log;
32import android.util.Pair;
33import android.util.SparseArray;
34
35import com.android.internal.annotations.Immutable;
36import com.android.internal.util.HexDump;
37import com.android.server.connectivity.KeepalivePacketData;
38import com.android.server.wifi.util.FrameParser;
39
40import java.io.PrintWriter;
41import java.io.StringWriter;
42import java.nio.ByteBuffer;
43import java.nio.CharBuffer;
44import java.nio.charset.CharacterCodingException;
45import java.nio.charset.CharsetDecoder;
46import java.nio.charset.StandardCharsets;
47import java.text.SimpleDateFormat;
48import java.util.ArrayList;
49import java.util.Date;
50import java.util.Map;
51import java.util.Objects;
52import java.util.Set;
53import 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 */
62public 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
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
78    public String getInterfaceName() {
79        return mInterfaceName;
80    }
81
82    /**
83     * Enable verbose logging for all sub modules.
84     */
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    */
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     */
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     */
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    */
184    public boolean disableSupplicant() {
185        return mWificondControl.disableSupplicant();
186    }
187
188    /**
189    * Enable wpa_supplicant via wificond.
190    * @return Returns true on success.
191    */
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    */
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    */
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     */
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     */
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     */
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     */
247    public boolean startPnoScan(PnoSettings pnoSettings) {
248        return mWificondControl.startPnoScan(pnoSettings);
249    }
250
251    /**
252     * Stop PNO scan.
253     * @return true on success.
254     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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      */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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         */
827        void onDeath();
828    }
829
830    /**
831     * Initializes the vendor HAL. This is just used to initialize the {@link HalDeviceManager}.
832     */
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     */
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     */
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     */
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     */
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
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
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
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
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         */
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         */
994        void onScanStatus(int event);
995        /**
996         * Called with the current cached scan results when gscan is paused.
997         */
998        void onScanPaused(WifiScanner.ScanData[] data);
999        /**
1000         * Called with the current cached scan results when gscan is resumed.
1001         */
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         */
1013        void onPnoNetworkFound(ScanResult[] results);
1014
1015        /**
1016         * Callback to notify when the PNO scan schedule fails.
1017         */
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     */
1034    public boolean startBgScan(ScanSettings settings, ScanEventHandler eventHandler) {
1035        return mWifiVendorHal.startBgScan(settings, eventHandler);
1036    }
1037
1038    /**
1039     * Stops any ongoing backgound scan
1040     */
1041    public void stopBgScan() {
1042        mWifiVendorHal.stopBgScan();
1043    }
1044
1045    /**
1046     * Pauses an ongoing backgound scan
1047     */
1048    public void pauseBgScan() {
1049        mWifiVendorHal.pauseBgScan();
1050    }
1051
1052    /**
1053     * Restarts a paused scan
1054     */
1055    public void restartBgScan() {
1056        mWifiVendorHal.restartBgScan();
1057    }
1058
1059    /**
1060     * Gets the latest scan results received.
1061     */
1062    public WifiScanner.ScanData[] getBgScanResults() {
1063        return mWifiVendorHal.getBgScanResults();
1064    }
1065
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     */
1075    public int getSupportedFeatureSet() {
1076        return mWifiVendorHal.getSupportedFeatureSet();
1077    }
1078
1079    public static interface RttEventHandler {
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     */
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     */
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
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     */
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     */
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     */
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     */
1153    public boolean isGetChannelsForBandSupported() {
1154        return mWifiVendorHal.isGetChannelsForBandSupported();
1155    }
1156
1157    /**
1158     * RTT (Round Trip Time) measurement capabilities of the device.
1159     */
1160    public RttManager.RttCapabilities getRttCapabilities() {
1161        return mWifiVendorHal.getRttCapabilities();
1162    }
1163
1164    /**
1165     * Get the APF (Android Packet Filter) capabilities of the device
1166     */
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     */
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     */
1187    public boolean setCountryCodeHal(String countryCode) {
1188        return mWifiVendorHal.setCountryCodeHal(countryCode);
1189    }
1190
1191    //---------------------------------------------------------------------------------
1192    /* Wifi Logger commands/events */
1193    public static interface WifiLoggerEventHandler {
1194        void onRingBufferData(RingBufferStatus status, 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     */
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     */
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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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     */
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
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
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
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(). */
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
1388        protected abstract String directionToString();
1389
1390        protected abstract String fateToString();
1391
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         */
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 {
1439        TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1440            super(fate, driverTimestampUSec, frameType, frameBytes);
1441        }
1442
1443        @Override
1444        protected String directionToString() {
1445            return "TX";
1446        }
1447
1448        @Override
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 {
1482        RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
1483            super(fate, driverTimestampUSec, frameType, frameBytes);
1484        }
1485
1486        @Override
1487        protected String directionToString() {
1488            return "RX";
1489        }
1490
1491        @Override
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     */
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     */
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     */
1543    public boolean getRxPktFates(RxFateReport[] reportBufs) {
1544        return mWifiVendorHal.getRxPktFates(reportBufs);
1545    }
1546
1547    /**
1548     * Set the PNO settings & the network list in HAL to start PNO.
1549     * @param settings PNO settings and network list.
1550     * @param eventHandler Handler to receive notifications back during PNO scan.
1551     * @return true if success, false otherwise
1552     */
1553    public boolean setPnoList(PnoSettings settings, PnoEventHandler eventHandler) {
1554        Log.e(mTAG, "setPnoList not supported");
1555        return false;
1556    }
1557
1558    /**
1559     * Reset the PNO settings in HAL to stop PNO.
1560     * @return true if success, false otherwise
1561     */
1562    public boolean resetPnoList() {
1563        Log.e(mTAG, "resetPnoList not supported");
1564        return false;
1565    }
1566
1567    /**
1568     * Start sending the specified keep alive packets periodically.
1569     *
1570     * @param slot Integer used to identify each request.
1571     * @param keepAlivePacket Raw packet contents to send.
1572     * @param period Period to use for sending these packets.
1573     * @return 0 for success, -1 for error
1574     */
1575    public int startSendingOffloadedPacket(int slot, KeepalivePacketData keepAlivePacket,
1576                                           int period) {
1577        String[] macAddrStr = getMacAddress().split(":");
1578        byte[] srcMac = new byte[6];
1579        for (int i = 0; i < 6; i++) {
1580            Integer hexVal = Integer.parseInt(macAddrStr[i], 16);
1581            srcMac[i] = hexVal.byteValue();
1582        }
1583        return mWifiVendorHal.startSendingOffloadedPacket(
1584                slot, srcMac, keepAlivePacket, period);
1585    }
1586
1587    /**
1588     * Stop sending the specified keep alive packets.
1589     *
1590     * @param slot id - same as startSendingOffloadedPacket call.
1591     * @return 0 for success, -1 for error
1592     */
1593    public int stopSendingOffloadedPacket(int slot) {
1594        return mWifiVendorHal.stopSendingOffloadedPacket(slot);
1595    }
1596
1597    public static interface WifiRssiEventHandler {
1598        void onRssiThresholdBreached(byte curRssi);
1599    }
1600
1601    /**
1602     * Start RSSI monitoring on the currently connected access point.
1603     *
1604     * @param maxRssi          Maximum RSSI threshold.
1605     * @param minRssi          Minimum RSSI threshold.
1606     * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi
1607     * @return 0 for success, -1 for failure
1608     */
1609    public int startRssiMonitoring(byte maxRssi, byte minRssi,
1610                                   WifiRssiEventHandler rssiEventHandler) {
1611        return mWifiVendorHal.startRssiMonitoring(maxRssi, minRssi, rssiEventHandler);
1612    }
1613
1614    public int stopRssiMonitoring() {
1615        return mWifiVendorHal.stopRssiMonitoring();
1616    }
1617
1618    /**
1619     * Fetch the host wakeup reasons stats from wlan driver.
1620     *
1621     * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver.
1622     */
1623    public WifiWakeReasonAndCounts getWlanWakeReasonCount() {
1624        return mWifiVendorHal.getWlanWakeReasonCount();
1625    }
1626
1627    /**
1628     * Enable/Disable Neighbour discovery offload functionality in the firmware.
1629     *
1630     * @param enabled true to enable, false to disable.
1631     * @return true for success, false otherwise.
1632     */
1633    public boolean configureNeighborDiscoveryOffload(boolean enabled) {
1634        return mWifiVendorHal.configureNeighborDiscoveryOffload(enabled);
1635    }
1636
1637    // Firmware roaming control.
1638
1639    /**
1640     * Class to retrieve firmware roaming capability parameters.
1641     */
1642    public static class RoamingCapabilities {
1643        public int  maxBlacklistSize;
1644        public int  maxWhitelistSize;
1645    }
1646
1647    /**
1648     * Query the firmware roaming capabilities.
1649     * @return true for success, false otherwise.
1650     */
1651    public boolean getRoamingCapabilities(RoamingCapabilities capabilities) {
1652        return mWifiVendorHal.getRoamingCapabilities(capabilities);
1653    }
1654
1655    /**
1656     * Macros for controlling firmware roaming.
1657     */
1658    public static final int DISABLE_FIRMWARE_ROAMING = 0;
1659    public static final int ENABLE_FIRMWARE_ROAMING = 1;
1660
1661    /**
1662     * Enable/disable firmware roaming.
1663     *
1664     * @return error code returned from HAL.
1665     */
1666    public int enableFirmwareRoaming(int state) {
1667        return mWifiVendorHal.enableFirmwareRoaming(state);
1668    }
1669
1670    /**
1671     * Class for specifying the roaming configurations.
1672     */
1673    public static class RoamingConfig {
1674        public ArrayList<String> blacklistBssids;
1675        public ArrayList<String> whitelistSsids;
1676    }
1677
1678    /**
1679     * Set firmware roaming configurations.
1680     */
1681    public boolean configureRoaming(RoamingConfig config) {
1682        Log.d(mTAG, "configureRoaming ");
1683        return mWifiVendorHal.configureRoaming(config);
1684    }
1685
1686    /**
1687     * Reset firmware roaming configuration.
1688     */
1689    public boolean resetRoamingConfiguration() {
1690        // Pass in an empty RoamingConfig object which translates to zero size
1691        // blacklist and whitelist to reset the firmware roaming configuration.
1692        return mWifiVendorHal.configureRoaming(new RoamingConfig());
1693    }
1694
1695    /**
1696     * Tx power level scenarios that can be selected.
1697     */
1698    public static final int TX_POWER_SCENARIO_NORMAL = 0;
1699    public static final int TX_POWER_SCENARIO_VOICE_CALL = 1;
1700
1701    /**
1702     * Select one of the pre-configured TX power level scenarios or reset it back to normal.
1703     * Primarily used for meeting SAR requirements during voice calls.
1704     *
1705     * @param scenario Should be one {@link #TX_POWER_SCENARIO_NORMAL} or
1706     *        {@link #TX_POWER_SCENARIO_VOICE_CALL}.
1707     * @return true for success; false for failure or if the HAL version does not support this API.
1708     */
1709    public boolean selectTxPowerScenario(int scenario) {
1710        return mWifiVendorHal.selectTxPowerScenario(scenario);
1711    }
1712
1713    /********************************************************
1714     * JNI operations
1715     ********************************************************/
1716    /* Register native functions */
1717    static {
1718        /* Native functions are defined in libwifi-service.so */
1719        System.loadLibrary("wifi-service");
1720        registerNatives();
1721    }
1722
1723    private static native int registerNatives();
1724    /* kernel logging support */
1725    private static native byte[] readKernelLogNative();
1726
1727    /**
1728     * Fetches the latest kernel logs.
1729     */
1730    public synchronized String readKernelLog() {
1731        byte[] bytes = readKernelLogNative();
1732        if (bytes != null) {
1733            CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
1734            try {
1735                CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
1736                return decoded.toString();
1737            } catch (CharacterCodingException cce) {
1738                return new String(bytes, StandardCharsets.ISO_8859_1);
1739            }
1740        } else {
1741            return "*** failed to read kernel log ***";
1742        }
1743    }
1744}
1745