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