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.IntDef;
     20 import android.annotation.NonNull;
     21 import android.annotation.Nullable;
     22 import android.net.InterfaceConfiguration;
     23 import android.net.MacAddress;
     24 import android.net.TrafficStats;
     25 import android.net.apf.ApfCapabilities;
     26 import android.net.wifi.RttManager;
     27 import android.net.wifi.RttManager.ResponderConfig;
     28 import android.net.wifi.ScanResult;
     29 import android.net.wifi.WifiConfiguration;
     30 import android.net.wifi.WifiScanner;
     31 import android.net.wifi.WifiWakeReasonAndCounts;
     32 import android.os.INetworkManagementService;
     33 import android.os.RemoteException;
     34 import android.os.SystemClock;
     35 import android.text.TextUtils;
     36 import android.util.Log;
     37 import android.util.SparseArray;
     38 
     39 import com.android.internal.annotations.Immutable;
     40 import com.android.internal.util.HexDump;
     41 import com.android.server.net.BaseNetworkObserver;
     42 import com.android.server.wifi.util.FrameParser;
     43 import com.android.server.wifi.util.NativeUtil;
     44 
     45 import java.io.PrintWriter;
     46 import java.io.StringWriter;
     47 import java.lang.annotation.Retention;
     48 import java.lang.annotation.RetentionPolicy;
     49 import java.nio.ByteBuffer;
     50 import java.nio.CharBuffer;
     51 import java.nio.charset.CharacterCodingException;
     52 import java.nio.charset.CharsetDecoder;
     53 import java.nio.charset.StandardCharsets;
     54 import java.text.SimpleDateFormat;
     55 import java.util.ArrayList;
     56 import java.util.Date;
     57 import java.util.HashMap;
     58 import java.util.HashSet;
     59 import java.util.Iterator;
     60 import java.util.Map;
     61 import java.util.Objects;
     62 import java.util.Set;
     63 import java.util.TimeZone;
     64 
     65 /**
     66  * Native calls for bring up/shut down of the supplicant daemon and for
     67  * sending requests to the supplicant daemon
     68  *
     69  * {@hide}
     70  */
     71 public class WifiNative {
     72     private static final String TAG = "WifiNative";
     73     private final SupplicantStaIfaceHal mSupplicantStaIfaceHal;
     74     private final HostapdHal mHostapdHal;
     75     private final WifiVendorHal mWifiVendorHal;
     76     private final WificondControl mWificondControl;
     77     private final WifiMonitor mWifiMonitor;
     78     private final INetworkManagementService mNwManagementService;
     79     private final PropertyService mPropertyService;
     80     private final WifiMetrics mWifiMetrics;
     81     private boolean mVerboseLoggingEnabled = false;
     82 
     83     public WifiNative(WifiVendorHal vendorHal,
     84                       SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal,
     85                       WificondControl condControl, WifiMonitor wifiMonitor,
     86                       INetworkManagementService nwService,
     87                       PropertyService propertyService, WifiMetrics wifiMetrics) {
     88         mWifiVendorHal = vendorHal;
     89         mSupplicantStaIfaceHal = staIfaceHal;
     90         mHostapdHal = hostapdHal;
     91         mWificondControl = condControl;
     92         mWifiMonitor = wifiMonitor;
     93         mNwManagementService = nwService;
     94         mPropertyService = propertyService;
     95         mWifiMetrics = wifiMetrics;
     96     }
     97 
     98     /**
     99      * Enable verbose logging for all sub modules.
    100      */
    101     public void enableVerboseLogging(int verbose) {
    102         mVerboseLoggingEnabled = verbose > 0 ? true : false;
    103         mWificondControl.enableVerboseLogging(mVerboseLoggingEnabled);
    104         mSupplicantStaIfaceHal.enableVerboseLogging(mVerboseLoggingEnabled);
    105         mWifiVendorHal.enableVerboseLogging(mVerboseLoggingEnabled);
    106     }
    107 
    108     /********************************************************
    109      * Interface management related methods.
    110      ********************************************************/
    111     /**
    112      * Meta-info about every iface that is active.
    113      */
    114     private static class Iface {
    115         /** Type of ifaces possible */
    116         public static final int IFACE_TYPE_AP = 0;
    117         public static final int IFACE_TYPE_STA = 1;
    118 
    119         @IntDef({IFACE_TYPE_AP, IFACE_TYPE_STA})
    120         @Retention(RetentionPolicy.SOURCE)
    121         public @interface IfaceType{}
    122 
    123         /** Identifier allocated for the interface */
    124         public final int id;
    125         /** Type of the iface: STA or AP */
    126         public final @IfaceType int type;
    127         /** Name of the interface */
    128         public String name;
    129         /** Is the interface up? This is used to mask up/down notifications to external clients. */
    130         public boolean isUp;
    131         /** External iface destroyed listener for the iface */
    132         public InterfaceCallback externalListener;
    133         /** Network observer registered for this interface */
    134         public NetworkObserverInternal networkObserver;
    135 
    136         Iface(int id, @Iface.IfaceType int type) {
    137             this.id = id;
    138             this.type = type;
    139         }
    140 
    141         @Override
    142         public String toString() {
    143             StringBuffer sb = new StringBuffer();
    144             sb.append("Iface:")
    145                 .append("{")
    146                 .append("Name=").append(name)
    147                 .append(",")
    148                 .append("Id=").append(id)
    149                 .append(",")
    150                 .append("Type=").append(type == IFACE_TYPE_STA ? "STA" : "AP")
    151                 .append("}");
    152             return sb.toString();
    153         }
    154     }
    155 
    156     /**
    157      * Iface Management entity. This class maintains list of all the active ifaces.
    158      */
    159     private static class IfaceManager {
    160         /** Integer to allocate for the next iface being created */
    161         private int mNextId;
    162         /** Map of the id to the iface structure */
    163         private HashMap<Integer, Iface> mIfaces = new HashMap<>();
    164 
    165         /** Allocate a new iface for the given type */
    166         private Iface allocateIface(@Iface.IfaceType  int type) {
    167             Iface iface = new Iface(mNextId, type);
    168             mIfaces.put(mNextId, iface);
    169             mNextId++;
    170             return iface;
    171         }
    172 
    173         /** Remove the iface using the provided id */
    174         private Iface removeIface(int id) {
    175             return mIfaces.remove(id);
    176         }
    177 
    178         /** Lookup the iface using the provided id */
    179         private Iface getIface(int id) {
    180             return mIfaces.get(id);
    181         }
    182 
    183         /** Lookup the iface using the provided name */
    184         private Iface getIface(@NonNull String ifaceName) {
    185             for (Iface iface : mIfaces.values()) {
    186                 if (TextUtils.equals(iface.name, ifaceName)) {
    187                     return iface;
    188                 }
    189             }
    190             return null;
    191         }
    192 
    193         /** Iterator to use for deleting all the ifaces while performing teardown on each of them */
    194         private Iterator<Integer> getIfaceIdIter() {
    195             return mIfaces.keySet().iterator();
    196         }
    197 
    198         /** Checks if there are any iface active. */
    199         private boolean hasAnyIface() {
    200             return !mIfaces.isEmpty();
    201         }
    202 
    203         /** Checks if there are any iface of the given type active. */
    204         private boolean hasAnyIfaceOfType(@Iface.IfaceType int type) {
    205             for (Iface iface : mIfaces.values()) {
    206                 if (iface.type == type) {
    207                     return true;
    208                 }
    209             }
    210             return false;
    211         }
    212 
    213         /** Checks if there are any iface of the given type active. */
    214         private Iface findAnyIfaceOfType(@Iface.IfaceType int type) {
    215             for (Iface iface : mIfaces.values()) {
    216                 if (iface.type == type) {
    217                     return iface;
    218                 }
    219             }
    220             return null;
    221         }
    222 
    223         /** Checks if there are any STA iface active. */
    224         private boolean hasAnyStaIface() {
    225             return hasAnyIfaceOfType(Iface.IFACE_TYPE_STA);
    226         }
    227 
    228         /** Checks if there are any AP iface active. */
    229         private boolean hasAnyApIface() {
    230             return hasAnyIfaceOfType(Iface.IFACE_TYPE_AP);
    231         }
    232 
    233         private String findAnyStaIfaceName() {
    234             Iface iface = findAnyIfaceOfType(Iface.IFACE_TYPE_STA);
    235             if (iface == null) {
    236                 return null;
    237             }
    238             return iface.name;
    239         }
    240 
    241         private String findAnyApIfaceName() {
    242             Iface iface = findAnyIfaceOfType(Iface.IFACE_TYPE_AP);
    243             if (iface == null) {
    244                 return null;
    245             }
    246             return iface.name;
    247         }
    248 
    249         /** Removes the existing iface that does not match the provided id. */
    250         public Iface removeExistingIface(int newIfaceId) {
    251             Iface removedIface = null;
    252             // The number of ifaces in the database could be 1 existing & 1 new at the max.
    253             if (mIfaces.size() > 2) {
    254                 Log.wtf(TAG, "More than 1 existing interface found");
    255             }
    256             Iterator<Map.Entry<Integer, Iface>> iter = mIfaces.entrySet().iterator();
    257             while (iter.hasNext()) {
    258                 Map.Entry<Integer, Iface> entry = iter.next();
    259                 if (entry.getKey() != newIfaceId) {
    260                     removedIface = entry.getValue();
    261                     iter.remove();
    262                 }
    263             }
    264             return removedIface;
    265         }
    266     }
    267 
    268     private Object mLock = new Object();
    269     private final IfaceManager mIfaceMgr = new IfaceManager();
    270     private HashSet<StatusListener> mStatusListeners = new HashSet<>();
    271 
    272     /** Helper method invoked to start supplicant if there were no ifaces */
    273     private boolean startHal() {
    274         synchronized (mLock) {
    275             if (!mIfaceMgr.hasAnyIface()) {
    276                 if (mWifiVendorHal.isVendorHalSupported()) {
    277                     if (!mWifiVendorHal.startVendorHal()) {
    278                         Log.e(TAG, "Failed to start vendor HAL");
    279                         return false;
    280                     }
    281                 } else {
    282                     Log.i(TAG, "Vendor Hal not supported, ignoring start.");
    283                 }
    284             }
    285             return true;
    286         }
    287     }
    288 
    289     /** Helper method invoked to stop HAL if there are no more ifaces */
    290     private void stopHalAndWificondIfNecessary() {
    291         synchronized (mLock) {
    292             if (!mIfaceMgr.hasAnyIface()) {
    293                 if (!mWificondControl.tearDownInterfaces()) {
    294                     Log.e(TAG, "Failed to teardown ifaces from wificond");
    295                 }
    296                 if (mWifiVendorHal.isVendorHalSupported()) {
    297                     mWifiVendorHal.stopVendorHal();
    298                 } else {
    299                     Log.i(TAG, "Vendor Hal not supported, ignoring stop.");
    300                 }
    301             }
    302         }
    303     }
    304 
    305     private static final int CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS = 100;
    306     private static final int CONNECT_TO_SUPPLICANT_RETRY_TIMES = 50;
    307     /**
    308      * This method is called to wait for establishing connection to wpa_supplicant.
    309      *
    310      * @return true if connection is established, false otherwise.
    311      */
    312     private boolean waitForSupplicantConnection() {
    313         // Start initialization if not already started.
    314         if (!mSupplicantStaIfaceHal.isInitializationStarted()
    315                 && !mSupplicantStaIfaceHal.initialize()) {
    316             return false;
    317         }
    318         boolean connected = false;
    319         int connectTries = 0;
    320         while (!connected && connectTries++ < CONNECT_TO_SUPPLICANT_RETRY_TIMES) {
    321             // Check if the initialization is complete.
    322             connected = mSupplicantStaIfaceHal.isInitializationComplete();
    323             if (connected) {
    324                 break;
    325             }
    326             try {
    327                 Thread.sleep(CONNECT_TO_SUPPLICANT_RETRY_INTERVAL_MS);
    328             } catch (InterruptedException ignore) {
    329             }
    330         }
    331         return connected;
    332     }
    333 
    334     /** Helper method invoked to start supplicant if there were no STA ifaces */
    335     private boolean startSupplicant() {
    336         synchronized (mLock) {
    337             if (!mIfaceMgr.hasAnyStaIface()) {
    338                 if (!mWificondControl.enableSupplicant()) {
    339                     Log.e(TAG, "Failed to enable supplicant");
    340                     return false;
    341                 }
    342                 if (!waitForSupplicantConnection()) {
    343                     Log.e(TAG, "Failed to connect to supplicant");
    344                     return false;
    345                 }
    346                 if (!mSupplicantStaIfaceHal.registerDeathHandler(
    347                         new SupplicantDeathHandlerInternal())) {
    348                     Log.e(TAG, "Failed to register supplicant death handler");
    349                     return false;
    350                 }
    351             }
    352             return true;
    353         }
    354     }
    355 
    356     /** Helper method invoked to stop supplicant if there are no more STA ifaces */
    357     private void stopSupplicantIfNecessary() {
    358         synchronized (mLock) {
    359             if (!mIfaceMgr.hasAnyStaIface()) {
    360                 if (!mSupplicantStaIfaceHal.deregisterDeathHandler()) {
    361                     Log.e(TAG, "Failed to deregister supplicant death handler");
    362                 }
    363                 if (!mWificondControl.disableSupplicant()) {
    364                     Log.e(TAG, "Failed to disable supplicant");
    365                 }
    366             }
    367         }
    368     }
    369 
    370     /** Helper method to register a network observer and return it */
    371     private boolean registerNetworkObserver(NetworkObserverInternal observer) {
    372         if (observer == null) return false;
    373         try {
    374             mNwManagementService.registerObserver(observer);
    375         } catch (RemoteException e) {
    376             return false;
    377         }
    378         return true;
    379     }
    380 
    381     /** Helper method to unregister a network observer */
    382     private boolean unregisterNetworkObserver(NetworkObserverInternal observer) {
    383         if (observer == null) return false;
    384         try {
    385             mNwManagementService.unregisterObserver(observer);
    386         } catch (RemoteException e) {
    387             return false;
    388         }
    389         return true;
    390     }
    391 
    392     /** Helper method invoked to teardown client iface and perform necessary cleanup */
    393     private void onClientInterfaceDestroyed(@NonNull Iface iface) {
    394         synchronized (mLock) {
    395             mWifiMonitor.stopMonitoring(iface.name);
    396             if (!unregisterNetworkObserver(iface.networkObserver)) {
    397                 Log.e(TAG, "Failed to unregister network observer on " + iface);
    398             }
    399             if (!mSupplicantStaIfaceHal.teardownIface(iface.name)) {
    400                 Log.e(TAG, "Failed to teardown iface in supplicant on " + iface);
    401             }
    402             if (!mWificondControl.tearDownClientInterface(iface.name)) {
    403                 Log.e(TAG, "Failed to teardown iface in wificond on " + iface);
    404             }
    405             stopSupplicantIfNecessary();
    406             stopHalAndWificondIfNecessary();
    407         }
    408     }
    409 
    410     /** Helper method invoked to teardown softAp iface and perform necessary cleanup */
    411     private void onSoftApInterfaceDestroyed(@NonNull Iface iface) {
    412         synchronized (mLock) {
    413             if (!unregisterNetworkObserver(iface.networkObserver)) {
    414                 Log.e(TAG, "Failed to unregister network observer on " + iface);
    415             }
    416             if (!mHostapdHal.removeAccessPoint(iface.name)) {
    417                 Log.e(TAG, "Failed to remove access point on " + iface);
    418             }
    419             if (!mHostapdHal.deregisterDeathHandler()) {
    420                 Log.e(TAG, "Failed to deregister supplicant death handler");
    421             }
    422             // TODO(b/71513606): Move this to a global operation.
    423             if (!mWificondControl.stopHostapd(iface.name)) {
    424                 Log.e(TAG, "Failed to stop hostapd on " + iface);
    425             }
    426             if (!mWificondControl.tearDownSoftApInterface(iface.name)) {
    427                 Log.e(TAG, "Failed to teardown iface in wificond on " + iface);
    428             }
    429             stopHalAndWificondIfNecessary();
    430         }
    431     }
    432 
    433     /** Helper method invoked to teardown iface and perform necessary cleanup */
    434     private void onInterfaceDestroyed(@NonNull Iface iface) {
    435         synchronized (mLock) {
    436             if (iface.type == Iface.IFACE_TYPE_STA) {
    437                 onClientInterfaceDestroyed(iface);
    438             } else if (iface.type == Iface.IFACE_TYPE_AP) {
    439                 onSoftApInterfaceDestroyed(iface);
    440             }
    441             // Invoke the external callback.
    442             iface.externalListener.onDestroyed(iface.name);
    443         }
    444     }
    445 
    446     /**
    447      * Callback to be invoked by HalDeviceManager when an interface is destroyed.
    448      */
    449     private class InterfaceDestoyedListenerInternal
    450             implements HalDeviceManager.InterfaceDestroyedListener {
    451         /** Identifier allocated for the interface */
    452         private final int mInterfaceId;
    453 
    454         InterfaceDestoyedListenerInternal(int ifaceId) {
    455             mInterfaceId = ifaceId;
    456         }
    457 
    458         @Override
    459         public void onDestroyed(@NonNull String ifaceName) {
    460             synchronized (mLock) {
    461                 final Iface iface = mIfaceMgr.removeIface(mInterfaceId);
    462                 if (iface == null) {
    463                     if (mVerboseLoggingEnabled) {
    464                         Log.v(TAG, "Received iface destroyed notification on an invalid iface="
    465                                 + ifaceName);
    466                     }
    467                     return;
    468                 }
    469                 onInterfaceDestroyed(iface);
    470                 Log.i(TAG, "Successfully torn down " + iface);
    471             }
    472         }
    473     }
    474 
    475     /**
    476      * Helper method invoked to trigger the status changed callback after one of the native
    477      * daemon's death.
    478      */
    479     private void onNativeDaemonDeath() {
    480         synchronized (mLock) {
    481             for (StatusListener listener : mStatusListeners) {
    482                 listener.onStatusChanged(false);
    483             }
    484             for (StatusListener listener : mStatusListeners) {
    485                 listener.onStatusChanged(true);
    486             }
    487         }
    488     }
    489 
    490     /**
    491      * Death handler for the Vendor HAL daemon.
    492      */
    493     private class VendorHalDeathHandlerInternal implements VendorHalDeathEventHandler {
    494         @Override
    495         public void onDeath() {
    496             synchronized (mLock) {
    497                 Log.i(TAG, "Vendor HAL died. Cleaning up internal state.");
    498                 onNativeDaemonDeath();
    499                 mWifiMetrics.incrementNumHalCrashes();
    500             }
    501         }
    502     }
    503 
    504     /**
    505      * Death handler for the wificond daemon.
    506      */
    507     private class WificondDeathHandlerInternal implements WificondDeathEventHandler {
    508         @Override
    509         public void onDeath() {
    510             synchronized (mLock) {
    511                 Log.i(TAG, "wificond died. Cleaning up internal state.");
    512                 onNativeDaemonDeath();
    513                 mWifiMetrics.incrementNumWificondCrashes();
    514             }
    515         }
    516     }
    517 
    518     /**
    519      * Death handler for the supplicant daemon.
    520      */
    521     private class SupplicantDeathHandlerInternal implements SupplicantDeathEventHandler {
    522         @Override
    523         public void onDeath() {
    524             synchronized (mLock) {
    525                 Log.i(TAG, "wpa_supplicant died. Cleaning up internal state.");
    526                 onNativeDaemonDeath();
    527                 mWifiMetrics.incrementNumSupplicantCrashes();
    528             }
    529         }
    530     }
    531 
    532     /**
    533      * Death handler for the hostapd daemon.
    534      */
    535     private class HostapdDeathHandlerInternal implements HostapdDeathEventHandler {
    536         @Override
    537         public void onDeath() {
    538             synchronized (mLock) {
    539                 Log.i(TAG, "hostapd died. Cleaning up internal state.");
    540                 onNativeDaemonDeath();
    541                 mWifiMetrics.incrementNumHostapdCrashes();
    542             }
    543         }
    544     }
    545 
    546     /** Helper method invoked to handle interface change. */
    547     private void onInterfaceStateChanged(Iface iface, boolean isUp) {
    548         synchronized (mLock) {
    549             // Mask multiple notifications with the same state.
    550             if (isUp == iface.isUp) {
    551                 if (mVerboseLoggingEnabled) {
    552                     Log.v(TAG, "Interface status unchanged on " + iface + " from " + isUp
    553                             + ", Ignoring...");
    554                 }
    555                 return;
    556             }
    557             Log.i(TAG, "Interface state changed on " + iface + ", isUp=" + isUp);
    558             if (isUp) {
    559                 iface.externalListener.onUp(iface.name);
    560             } else {
    561                 iface.externalListener.onDown(iface.name);
    562                 if (iface.type == Iface.IFACE_TYPE_STA) {
    563                     mWifiMetrics.incrementNumClientInterfaceDown();
    564                 } else if (iface.type == Iface.IFACE_TYPE_AP) {
    565                     mWifiMetrics.incrementNumSoftApInterfaceDown();
    566                 }
    567             }
    568             iface.isUp = isUp;
    569         }
    570     }
    571 
    572     /**
    573      * Network observer to use for all interface up/down notifications.
    574      */
    575     private class NetworkObserverInternal extends BaseNetworkObserver {
    576         /** Identifier allocated for the interface */
    577         private final int mInterfaceId;
    578 
    579         NetworkObserverInternal(int id) {
    580             mInterfaceId = id;
    581         }
    582 
    583         // TODO(b/76219766): We may need to listen for link state changes in SoftAp mode.
    584         /**
    585          * Note: We should ideally listen to
    586          * {@link BaseNetworkObserver#interfaceStatusChanged(String, boolean)} here. But, that
    587          * callback is not working currently (broken in netd). So, instead listen to link state
    588          * change callbacks as triggers to query the real interface state. We should get rid of
    589          * this workaround if we get the |interfaceStatusChanged| callback to work in netd.
    590          * Also, this workaround will not detect an interface up event, if the link state is
    591          * still down.
    592          */
    593         @Override
    594         public void interfaceLinkStateChanged(String ifaceName, boolean unusedIsLinkUp) {
    595             synchronized (mLock) {
    596                 final Iface ifaceWithId = mIfaceMgr.getIface(mInterfaceId);
    597                 if (ifaceWithId == null) {
    598                     if (mVerboseLoggingEnabled) {
    599                         Log.v(TAG, "Received iface link up/down notification on an invalid iface="
    600                                 + mInterfaceId);
    601                     }
    602                     return;
    603                 }
    604                 final Iface ifaceWithName = mIfaceMgr.getIface(ifaceName);
    605                 if (ifaceWithName == null || ifaceWithName != ifaceWithId) {
    606                     if (mVerboseLoggingEnabled) {
    607                         Log.v(TAG, "Received iface link up/down notification on an invalid iface="
    608                                 + ifaceName);
    609                     }
    610                     return;
    611                 }
    612                 onInterfaceStateChanged(ifaceWithName, isInterfaceUp(ifaceName));
    613             }
    614         }
    615     }
    616 
    617     /**
    618      * Radio mode change handler for the Vendor HAL daemon.
    619      */
    620     private class VendorHalRadioModeChangeHandlerInternal
    621             implements VendorHalRadioModeChangeEventHandler {
    622         @Override
    623         public void onMcc(int band) {
    624             synchronized (mLock) {
    625                 Log.i(TAG, "Device is in MCC mode now");
    626                 mWifiMetrics.incrementNumRadioModeChangeToMcc();
    627             }
    628         }
    629         @Override
    630         public void onScc(int band) {
    631             synchronized (mLock) {
    632                 Log.i(TAG, "Device is in SCC mode now");
    633                 mWifiMetrics.incrementNumRadioModeChangeToScc();
    634             }
    635         }
    636         @Override
    637         public void onSbs(int band) {
    638             synchronized (mLock) {
    639                 Log.i(TAG, "Device is in SBS mode now");
    640                 mWifiMetrics.incrementNumRadioModeChangeToSbs();
    641             }
    642         }
    643         @Override
    644         public void onDbs() {
    645             synchronized (mLock) {
    646                 Log.i(TAG, "Device is in DBS mode now");
    647                 mWifiMetrics.incrementNumRadioModeChangeToDbs();
    648             }
    649         }
    650     }
    651 
    652     // For devices that don't support the vendor HAL, we will not support any concurrency.
    653     // So simulate the HalDeviceManager behavior by triggering the destroy listener for
    654     // any active interface.
    655     private String handleIfaceCreationWhenVendorHalNotSupported(@NonNull Iface newIface) {
    656         synchronized (mLock) {
    657             Iface existingIface = mIfaceMgr.removeExistingIface(newIface.id);
    658             if (existingIface != null) {
    659                 onInterfaceDestroyed(existingIface);
    660                 Log.i(TAG, "Successfully torn down " + existingIface);
    661             }
    662             // Return the interface name directly from the system property.
    663             return mPropertyService.getString("wifi.interface", "wlan0");
    664         }
    665     }
    666 
    667     /**
    668      * Helper function to handle creation of STA iface.
    669      * For devices which do not the support the HAL, this will bypass HalDeviceManager &
    670      * teardown any existing iface.
    671      */
    672     private String createStaIface(@NonNull Iface iface, boolean lowPrioritySta) {
    673         synchronized (mLock) {
    674             if (mWifiVendorHal.isVendorHalSupported()) {
    675                 return mWifiVendorHal.createStaIface(lowPrioritySta,
    676                         new InterfaceDestoyedListenerInternal(iface.id));
    677             } else {
    678                 Log.i(TAG, "Vendor Hal not supported, ignoring createStaIface.");
    679                 return handleIfaceCreationWhenVendorHalNotSupported(iface);
    680             }
    681         }
    682     }
    683 
    684     /**
    685      * Helper function to handle creation of AP iface.
    686      * For devices which do not the support the HAL, this will bypass HalDeviceManager &
    687      * teardown any existing iface.
    688      */
    689     private String createApIface(@NonNull Iface iface) {
    690         synchronized (mLock) {
    691             if (mWifiVendorHal.isVendorHalSupported()) {
    692                 return mWifiVendorHal.createApIface(
    693                         new InterfaceDestoyedListenerInternal(iface.id));
    694             } else {
    695                 Log.i(TAG, "Vendor Hal not supported, ignoring createApIface.");
    696                 return handleIfaceCreationWhenVendorHalNotSupported(iface);
    697             }
    698         }
    699     }
    700 
    701     // For devices that don't support the vendor HAL, we will not support any concurrency.
    702     // So simulate the HalDeviceManager behavior by triggering the destroy listener for
    703     // the interface.
    704     private boolean handleIfaceRemovalWhenVendorHalNotSupported(@NonNull Iface iface) {
    705         synchronized (mLock) {
    706             mIfaceMgr.removeIface(iface.id);
    707             onInterfaceDestroyed(iface);
    708             Log.i(TAG, "Successfully torn down " + iface);
    709             return true;
    710         }
    711     }
    712 
    713     /**
    714      * Helper function to handle removal of STA iface.
    715      * For devices which do not the support the HAL, this will bypass HalDeviceManager &
    716      * teardown any existing iface.
    717      */
    718     private boolean removeStaIface(@NonNull Iface iface) {
    719         synchronized (mLock) {
    720             if (mWifiVendorHal.isVendorHalSupported()) {
    721                 return mWifiVendorHal.removeStaIface(iface.name);
    722             } else {
    723                 Log.i(TAG, "Vendor Hal not supported, ignoring removeStaIface.");
    724                 return handleIfaceRemovalWhenVendorHalNotSupported(iface);
    725             }
    726         }
    727     }
    728 
    729     /**
    730      * Helper function to handle removal of STA iface.
    731      */
    732     private boolean removeApIface(@NonNull Iface iface) {
    733         synchronized (mLock) {
    734             if (mWifiVendorHal.isVendorHalSupported()) {
    735                 return mWifiVendorHal.removeApIface(iface.name);
    736             } else {
    737                 Log.i(TAG, "Vendor Hal not supported, ignoring removeApIface.");
    738                 return handleIfaceRemovalWhenVendorHalNotSupported(iface);
    739             }
    740         }
    741     }
    742 
    743     /**
    744      * Initialize the native modules.
    745      *
    746      * @return true on success, false otherwise.
    747      */
    748     public boolean initialize() {
    749         synchronized (mLock) {
    750             if (!mWifiVendorHal.initialize(new VendorHalDeathHandlerInternal())) {
    751                 Log.e(TAG, "Failed to initialize vendor HAL");
    752                 return false;
    753             }
    754             if (!mWificondControl.initialize(new WificondDeathHandlerInternal())) {
    755                 Log.e(TAG, "Failed to initialize wificond");
    756                 return false;
    757             }
    758             mWifiVendorHal.registerRadioModeChangeHandler(
    759                     new VendorHalRadioModeChangeHandlerInternal());
    760             return true;
    761         }
    762     }
    763 
    764     /**
    765      * Callback to notify when the status of one of the native daemons
    766      * (wificond, wpa_supplicant & vendor HAL) changes.
    767      */
    768     public interface StatusListener {
    769         /**
    770          * @param allReady Indicates if all the native daemons are ready for operation or not.
    771          */
    772         void onStatusChanged(boolean allReady);
    773     }
    774 
    775     /**
    776      * Register a StatusListener to get notified about any status changes from the native daemons.
    777      *
    778      * It is safe to re-register the same callback object - duplicates are detected and only a
    779      * single copy kept.
    780      *
    781      * @param listener StatusListener listener object.
    782      */
    783     public void registerStatusListener(@NonNull StatusListener listener) {
    784         mStatusListeners.add(listener);
    785     }
    786 
    787     /**
    788      * Callback to notify when the associated interface is destroyed, up or down.
    789      */
    790     public interface InterfaceCallback {
    791         /**
    792          * Interface destroyed by HalDeviceManager.
    793          *
    794          * @param ifaceName Name of the iface.
    795          */
    796         void onDestroyed(String ifaceName);
    797 
    798         /**
    799          * Interface is up.
    800          *
    801          * @param ifaceName Name of the iface.
    802          */
    803         void onUp(String ifaceName);
    804 
    805         /**
    806          * Interface is down.
    807          *
    808          * @param ifaceName Name of the iface.
    809          */
    810         void onDown(String ifaceName);
    811     }
    812 
    813     private void initializeNwParamsForClientInterface(@NonNull String ifaceName) {
    814         try {
    815             // A runtime crash or shutting down AP mode can leave
    816             // IP addresses configured, and this affects
    817             // connectivity when supplicant starts up.
    818             // Ensure we have no IP addresses before a supplicant start.
    819             mNwManagementService.clearInterfaceAddresses(ifaceName);
    820 
    821             // Set privacy extensions
    822             mNwManagementService.setInterfaceIpv6PrivacyExtensions(ifaceName, true);
    823 
    824             // IPv6 is enabled only as long as access point is connected since:
    825             // - IPv6 addresses and routes stick around after disconnection
    826             // - kernel is unaware when connected and fails to start IPv6 negotiation
    827             // - kernel can start autoconfiguration when 802.1x is not complete
    828             mNwManagementService.disableIpv6(ifaceName);
    829         } catch (RemoteException re) {
    830             Log.e(TAG, "Unable to change interface settings: " + re);
    831         } catch (IllegalStateException ie) {
    832             Log.e(TAG, "Unable to change interface settings: " + ie);
    833         }
    834     }
    835 
    836     /**
    837      * Setup an interface for Client mode operations.
    838      *
    839      * This method configures an interface in STA mode in all the native daemons
    840      * (wificond, wpa_supplicant & vendor HAL).
    841      *
    842      * @param lowPrioritySta The requested STA has a low request priority (lower probability of
    843      *                       getting created, higher probability of getting destroyed).
    844      * @param interfaceCallback Associated callback for notifying status changes for the iface.
    845      * @return Returns the name of the allocated interface, will be null on failure.
    846      */
    847     public String setupInterfaceForClientMode(boolean lowPrioritySta,
    848             @NonNull InterfaceCallback interfaceCallback) {
    849         synchronized (mLock) {
    850             if (!startHal()) {
    851                 Log.e(TAG, "Failed to start Hal");
    852                 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
    853                 return null;
    854             }
    855             if (!startSupplicant()) {
    856                 Log.e(TAG, "Failed to start supplicant");
    857                 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
    858                 return null;
    859             }
    860             Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA);
    861             if (iface == null) {
    862                 Log.e(TAG, "Failed to allocate new STA iface");
    863                 return null;
    864             }
    865             iface.externalListener = interfaceCallback;
    866             iface.name = createStaIface(iface, lowPrioritySta);
    867             if (TextUtils.isEmpty(iface.name)) {
    868                 Log.e(TAG, "Failed to create STA iface in vendor HAL");
    869                 mIfaceMgr.removeIface(iface.id);
    870                 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
    871                 return null;
    872             }
    873             if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {
    874                 Log.e(TAG, "Failed to setup iface in wificond on " + iface);
    875                 teardownInterface(iface.name);
    876                 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
    877                 return null;
    878             }
    879             if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
    880                 Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
    881                 teardownInterface(iface.name);
    882                 mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
    883                 return null;
    884             }
    885             iface.networkObserver = new NetworkObserverInternal(iface.id);
    886             if (!registerNetworkObserver(iface.networkObserver)) {
    887                 Log.e(TAG, "Failed to register network observer on " + iface);
    888                 teardownInterface(iface.name);
    889                 return null;
    890             }
    891             mWifiMonitor.startMonitoring(iface.name);
    892             // Just to avoid any race conditions with interface state change callbacks,
    893             // update the interface state before we exit.
    894             onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
    895             initializeNwParamsForClientInterface(iface.name);
    896             Log.i(TAG, "Successfully setup " + iface);
    897             return iface.name;
    898         }
    899     }
    900 
    901     /**
    902      * Setup an interface for Soft AP mode operations.
    903      *
    904      * This method configures an interface in AP mode in all the native daemons
    905      * (wificond, wpa_supplicant & vendor HAL).
    906      *
    907      * @param interfaceCallback Associated callback for notifying status changes for the iface.
    908      * @return Returns the name of the allocated interface, will be null on failure.
    909      */
    910     public String setupInterfaceForSoftApMode(@NonNull InterfaceCallback interfaceCallback) {
    911         synchronized (mLock) {
    912             if (!startHal()) {
    913                 Log.e(TAG, "Failed to start Hal");
    914                 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal();
    915                 return null;
    916             }
    917             Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_AP);
    918             if (iface == null) {
    919                 Log.e(TAG, "Failed to allocate new AP iface");
    920                 return null;
    921             }
    922             iface.externalListener = interfaceCallback;
    923             iface.name = createApIface(iface);
    924             if (TextUtils.isEmpty(iface.name)) {
    925                 Log.e(TAG, "Failed to create AP iface in vendor HAL");
    926                 mIfaceMgr.removeIface(iface.id);
    927                 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHal();
    928                 return null;
    929             }
    930             if (mWificondControl.setupInterfaceForSoftApMode(iface.name) == null) {
    931                 Log.e(TAG, "Failed to setup iface in wificond on " + iface);
    932                 teardownInterface(iface.name);
    933                 mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToWificond();
    934                 return null;
    935             }
    936             iface.networkObserver = new NetworkObserverInternal(iface.id);
    937             if (!registerNetworkObserver(iface.networkObserver)) {
    938                 Log.e(TAG, "Failed to register network observer on " + iface);
    939                 teardownInterface(iface.name);
    940                 return null;
    941             }
    942             // Just to avoid any race conditions with interface state change callbacks,
    943             // update the interface state before we exit.
    944             onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
    945             Log.i(TAG, "Successfully setup " + iface);
    946             return iface.name;
    947         }
    948     }
    949 
    950     /**
    951      *
    952      * Check if the interface is up or down.
    953      *
    954      * @param ifaceName Name of the interface.
    955      * @return true if iface is up, false if it's down or on error.
    956      */
    957     public boolean isInterfaceUp(@NonNull String ifaceName) {
    958         synchronized (mLock) {
    959             final Iface iface = mIfaceMgr.getIface(ifaceName);
    960             if (iface == null) {
    961                 Log.e(TAG, "Trying to get iface state on invalid iface=" + ifaceName);
    962                 return false;
    963             }
    964             InterfaceConfiguration config = null;
    965             try {
    966                 config = mNwManagementService.getInterfaceConfig(ifaceName);
    967             } catch (RemoteException e) {
    968             }
    969             if (config == null) {
    970                 return false;
    971             }
    972             return config.isUp();
    973         }
    974     }
    975 
    976     /**
    977      * Teardown an interface in Client/AP mode.
    978      *
    979      * This method tears down the associated interface from all the native daemons
    980      * (wificond, wpa_supplicant & vendor HAL).
    981      * Also, brings down the HAL, supplicant or hostapd as necessary.
    982      *
    983      * @param ifaceName Name of the interface.
    984      */
    985     public void teardownInterface(@NonNull String ifaceName) {
    986         synchronized (mLock) {
    987             final Iface iface = mIfaceMgr.getIface(ifaceName);
    988             if (iface == null) {
    989                 Log.e(TAG, "Trying to teardown an invalid iface=" + ifaceName);
    990                 return;
    991             }
    992             // Trigger the iface removal from HAL. The rest of the cleanup will be triggered
    993             // from the interface destroyed callback.
    994             if (iface.type == Iface.IFACE_TYPE_STA) {
    995                 if (!removeStaIface(iface)) {
    996                     Log.e(TAG, "Failed to remove iface in vendor HAL=" + ifaceName);
    997                     return;
    998                 }
    999             } else if (iface.type == Iface.IFACE_TYPE_AP) {
   1000                 if (!removeApIface(iface)) {
   1001                     Log.e(TAG, "Failed to remove iface in vendor HAL=" + ifaceName);
   1002                     return;
   1003                 }
   1004             }
   1005             Log.i(TAG, "Successfully initiated teardown for iface=" + ifaceName);
   1006         }
   1007     }
   1008 
   1009     /**
   1010      * Teardown all the active interfaces.
   1011      *
   1012      * This method tears down the associated interfaces from all the native daemons
   1013      * (wificond, wpa_supplicant & vendor HAL).
   1014      * Also, brings down the HAL, supplicant or hostapd as necessary.
   1015      */
   1016     public void teardownAllInterfaces() {
   1017         synchronized (mLock) {
   1018             Iterator<Integer> ifaceIdIter = mIfaceMgr.getIfaceIdIter();
   1019             while (ifaceIdIter.hasNext()) {
   1020                 Iface iface = mIfaceMgr.getIface(ifaceIdIter.next());
   1021                 ifaceIdIter.remove();
   1022                 onInterfaceDestroyed(iface);
   1023                 Log.i(TAG, "Successfully torn down " + iface);
   1024             }
   1025             Log.i(TAG, "Successfully torn down all ifaces");
   1026         }
   1027     }
   1028 
   1029     /**
   1030      * Get name of the client interface.
   1031      *
   1032      * This is mainly used by external modules that needs to perform some
   1033      * client operations on the STA interface.
   1034      *
   1035      * TODO(b/70932231): This may need to be reworked once we start supporting STA + STA.
   1036      *
   1037      * @return Interface name of any active client interface, null if no active client interface
   1038      * exist.
   1039      * Return Values for the different scenarios are listed below:
   1040      * a) When there are no client interfaces, returns null.
   1041      * b) when there is 1 client interface, returns the name of that interface.
   1042      * c) When there are 2 or more client interface, returns the name of any client interface.
   1043      */
   1044     public String getClientInterfaceName() {
   1045         synchronized (mLock) {
   1046             return mIfaceMgr.findAnyStaIfaceName();
   1047         }
   1048     }
   1049 
   1050     /**
   1051      * Get name of the softap interface.
   1052      *
   1053      * This is mainly used by external modules that needs to perform some
   1054      * operations on the AP interface.
   1055      *
   1056      * TODO(b/70932231): This may need to be reworked once we start supporting AP + AP.
   1057      *
   1058      * @return Interface name of any active softap interface, null if no active softap interface
   1059      * exist.
   1060      * Return Values for the different scenarios are listed below:
   1061      * a) When there are no softap interfaces, returns null.
   1062      * b) when there is 1 softap interface, returns the name of that interface.
   1063      * c) When there are 2 or more softap interface, returns the name of any softap interface.
   1064      */
   1065     public String getSoftApInterfaceName() {
   1066         synchronized (mLock) {
   1067             return mIfaceMgr.findAnyApIfaceName();
   1068         }
   1069     }
   1070 
   1071     /********************************************************
   1072      * Wificond operations
   1073      ********************************************************/
   1074     /**
   1075      * Result of a signal poll.
   1076      */
   1077     public static class SignalPollResult {
   1078         // RSSI value in dBM.
   1079         public int currentRssi;
   1080         //Transmission bit rate in Mbps.
   1081         public int txBitrate;
   1082         // Association frequency in MHz.
   1083         public int associationFrequency;
   1084     }
   1085 
   1086     /**
   1087      * WiFi interface transimission counters.
   1088      */
   1089     public static class TxPacketCounters {
   1090         // Number of successfully transmitted packets.
   1091         public int txSucceeded;
   1092         // Number of tramsmission failures.
   1093         public int txFailed;
   1094     }
   1095 
   1096     /**
   1097      * Callback to notify wificond death.
   1098      */
   1099     public interface WificondDeathEventHandler {
   1100         /**
   1101          * Invoked when the wificond dies.
   1102          */
   1103         void onDeath();
   1104     }
   1105 
   1106     /**
   1107      * Request signal polling to wificond.
   1108      *
   1109      * @param ifaceName Name of the interface.
   1110      * Returns an SignalPollResult object.
   1111      * Returns null on failure.
   1112      */
   1113     public SignalPollResult signalPoll(@NonNull String ifaceName) {
   1114         return mWificondControl.signalPoll(ifaceName);
   1115     }
   1116 
   1117     /**
   1118      * Fetch TX packet counters on current connection from wificond.
   1119      * @param ifaceName Name of the interface.
   1120      * Returns an TxPacketCounters object.
   1121      * Returns null on failure.
   1122      */
   1123     public TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) {
   1124         return mWificondControl.getTxPacketCounters(ifaceName);
   1125     }
   1126 
   1127     /**
   1128      * Query the list of valid frequencies for the provided band.
   1129      * The result depends on the on the country code that has been set.
   1130      *
   1131      * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants.
   1132      * The following bands are supported:
   1133      * WifiScanner.WIFI_BAND_24_GHZ
   1134      * WifiScanner.WIFI_BAND_5_GHZ
   1135      * WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY
   1136      * @return frequencies vector of valid frequencies (MHz), or null for error.
   1137      * @throws IllegalArgumentException if band is not recognized.
   1138      */
   1139     public int [] getChannelsForBand(int band) {
   1140         return mWificondControl.getChannelsForBand(band);
   1141     }
   1142 
   1143     /**
   1144      * Start a scan using wificond for the given parameters.
   1145      * @param ifaceName Name of the interface.
   1146      * @param scanType Type of scan to perform. One of {@link ScanSettings#SCAN_TYPE_LOW_LATENCY},
   1147      * {@link ScanSettings#SCAN_TYPE_LOW_POWER} or {@link ScanSettings#SCAN_TYPE_HIGH_ACCURACY}.
   1148      * @param freqs list of frequencies to scan for, if null scan all supported channels.
   1149      * @param hiddenNetworkSSIDs List of hidden networks to be scanned for.
   1150      * @return Returns true on success.
   1151      */
   1152     public boolean scan(
   1153             @NonNull String ifaceName, int scanType, Set<Integer> freqs,
   1154             Set<String> hiddenNetworkSSIDs) {
   1155         return mWificondControl.scan(ifaceName, scanType, freqs, hiddenNetworkSSIDs);
   1156     }
   1157 
   1158     /**
   1159      * Fetch the latest scan result from kernel via wificond.
   1160      * @param ifaceName Name of the interface.
   1161      * @return Returns an ArrayList of ScanDetail.
   1162      * Returns an empty ArrayList on failure.
   1163      */
   1164     public ArrayList<ScanDetail> getScanResults(@NonNull String ifaceName) {
   1165         return mWificondControl.getScanResults(
   1166                 ifaceName, WificondControl.SCAN_TYPE_SINGLE_SCAN);
   1167     }
   1168 
   1169     /**
   1170      * Fetch the latest scan result from kernel via wificond.
   1171      * @param ifaceName Name of the interface.
   1172      * @return Returns an ArrayList of ScanDetail.
   1173      * Returns an empty ArrayList on failure.
   1174      */
   1175     public ArrayList<ScanDetail> getPnoScanResults(@NonNull String ifaceName) {
   1176         return mWificondControl.getScanResults(ifaceName, WificondControl.SCAN_TYPE_PNO_SCAN);
   1177     }
   1178 
   1179     /**
   1180      * Start PNO scan.
   1181      * @param ifaceName Name of the interface.
   1182      * @param pnoSettings Pno scan configuration.
   1183      * @return true on success.
   1184      */
   1185     public boolean startPnoScan(@NonNull String ifaceName, PnoSettings pnoSettings) {
   1186         return mWificondControl.startPnoScan(ifaceName, pnoSettings);
   1187     }
   1188 
   1189     /**
   1190      * Stop PNO scan.
   1191      * @param ifaceName Name of the interface.
   1192      * @return true on success.
   1193      */
   1194     public boolean stopPnoScan(@NonNull String ifaceName) {
   1195         return mWificondControl.stopPnoScan(ifaceName);
   1196     }
   1197 
   1198     /**
   1199      * Callbacks for SoftAp interface.
   1200      */
   1201     public interface SoftApListener {
   1202         /**
   1203          * Invoked when the number of associated stations changes.
   1204          */
   1205         void onNumAssociatedStationsChanged(int numStations);
   1206 
   1207         /**
   1208          * Invoked when the channel switch event happens.
   1209          */
   1210         void onSoftApChannelSwitched(int frequency, int bandwidth);
   1211     }
   1212 
   1213     private static final int CONNECT_TO_HOSTAPD_RETRY_INTERVAL_MS = 100;
   1214     private static final int CONNECT_TO_HOSTAPD_RETRY_TIMES = 50;
   1215     /**
   1216      * This method is called to wait for establishing connection to hostapd.
   1217      *
   1218      * @return true if connection is established, false otherwise.
   1219      */
   1220     private boolean waitForHostapdConnection() {
   1221         // Start initialization if not already started.
   1222         if (!mHostapdHal.isInitializationStarted()
   1223                 && !mHostapdHal.initialize()) {
   1224             return false;
   1225         }
   1226         boolean connected = false;
   1227         int connectTries = 0;
   1228         while (!connected && connectTries++ < CONNECT_TO_HOSTAPD_RETRY_TIMES) {
   1229             // Check if the initialization is complete.
   1230             connected = mHostapdHal.isInitializationComplete();
   1231             if (connected) {
   1232                 break;
   1233             }
   1234             try {
   1235                 Thread.sleep(CONNECT_TO_HOSTAPD_RETRY_INTERVAL_MS);
   1236             } catch (InterruptedException ignore) {
   1237             }
   1238         }
   1239         return connected;
   1240     }
   1241 
   1242     /**
   1243      * Start Soft AP operation using the provided configuration.
   1244      *
   1245      * @param ifaceName Name of the interface.
   1246      * @param config Configuration to use for the soft ap created.
   1247      * @param listener Callback for AP events.
   1248      * @return true on success, false otherwise.
   1249      */
   1250     public boolean startSoftAp(
   1251             @NonNull String ifaceName, WifiConfiguration config, SoftApListener listener) {
   1252         if (!mWificondControl.startHostapd(ifaceName, listener)) {
   1253             Log.e(TAG, "Failed to start hostapd");
   1254             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
   1255             return false;
   1256         }
   1257         if (!waitForHostapdConnection()) {
   1258             Log.e(TAG, "Failed to establish connection to hostapd");
   1259             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
   1260             return false;
   1261         }
   1262         if (!mHostapdHal.registerDeathHandler(new HostapdDeathHandlerInternal())) {
   1263             Log.e(TAG, "Failed to register hostapd death handler");
   1264             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
   1265             return false;
   1266         }
   1267         if (!mHostapdHal.addAccessPoint(ifaceName, config)) {
   1268             Log.e(TAG, "Failed to add acccess point");
   1269             mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();
   1270             return false;
   1271         }
   1272         return true;
   1273     }
   1274 
   1275     /**
   1276      * Stop the ongoing Soft AP operation.
   1277      *
   1278      * @param ifaceName Name of the interface.
   1279      * @return true on success, false otherwise.
   1280      */
   1281     public boolean stopSoftAp(@NonNull String ifaceName) {
   1282         if (!mHostapdHal.removeAccessPoint(ifaceName)) {
   1283             Log.e(TAG, "Failed to remove access point");
   1284         }
   1285         return mWificondControl.stopHostapd(ifaceName);
   1286     }
   1287 
   1288     /**
   1289      * Set MAC address of the given interface
   1290      * @param interfaceName Name of the interface
   1291      * @param mac Mac address to change into
   1292      * @return true on success
   1293      */
   1294     public boolean setMacAddress(String interfaceName, MacAddress mac) {
   1295         // TODO(b/72459123): Suppress interface down/up events from this call
   1296         return mWifiVendorHal.setMacAddress(interfaceName, mac);
   1297     }
   1298 
   1299     /********************************************************
   1300      * Hostapd operations
   1301      ********************************************************/
   1302 
   1303     /**
   1304      * Callback to notify hostapd death.
   1305      */
   1306     public interface HostapdDeathEventHandler {
   1307         /**
   1308          * Invoked when the supplicant dies.
   1309          */
   1310         void onDeath();
   1311     }
   1312 
   1313     /********************************************************
   1314      * Supplicant operations
   1315      ********************************************************/
   1316 
   1317     /**
   1318      * Callback to notify supplicant death.
   1319      */
   1320     public interface SupplicantDeathEventHandler {
   1321         /**
   1322          * Invoked when the supplicant dies.
   1323          */
   1324         void onDeath();
   1325     }
   1326 
   1327     /**
   1328      * Set supplicant log level
   1329      *
   1330      * @param turnOnVerbose Whether to turn on verbose logging or not.
   1331      */
   1332     public void setSupplicantLogLevel(boolean turnOnVerbose) {
   1333         mSupplicantStaIfaceHal.setLogLevel(turnOnVerbose);
   1334     }
   1335 
   1336     /**
   1337      * Trigger a reconnection if the iface is disconnected.
   1338      *
   1339      * @param ifaceName Name of the interface.
   1340      * @return true if request is sent successfully, false otherwise.
   1341      */
   1342     public boolean reconnect(@NonNull String ifaceName) {
   1343         return mSupplicantStaIfaceHal.reconnect(ifaceName);
   1344     }
   1345 
   1346     /**
   1347      * Trigger a reassociation even if the iface is currently connected.
   1348      *
   1349      * @param ifaceName Name of the interface.
   1350      * @return true if request is sent successfully, false otherwise.
   1351      */
   1352     public boolean reassociate(@NonNull String ifaceName) {
   1353         return mSupplicantStaIfaceHal.reassociate(ifaceName);
   1354     }
   1355 
   1356     /**
   1357      * Trigger a disconnection from the currently connected network.
   1358      *
   1359      * @param ifaceName Name of the interface.
   1360      * @return true if request is sent successfully, false otherwise.
   1361      */
   1362     public boolean disconnect(@NonNull String ifaceName) {
   1363         return mSupplicantStaIfaceHal.disconnect(ifaceName);
   1364     }
   1365 
   1366     /**
   1367      * Makes a callback to HIDL to getMacAddress from supplicant
   1368      *
   1369      * @param ifaceName Name of the interface.
   1370      * @return string containing the MAC address, or null on a failed call
   1371      */
   1372     public String getMacAddress(@NonNull String ifaceName) {
   1373         return mSupplicantStaIfaceHal.getMacAddress(ifaceName);
   1374     }
   1375 
   1376     public static final int RX_FILTER_TYPE_V4_MULTICAST = 0;
   1377     public static final int RX_FILTER_TYPE_V6_MULTICAST = 1;
   1378     /**
   1379      * Start filtering out Multicast V4 packets
   1380      * @param ifaceName Name of the interface.
   1381      * @return {@code true} if the operation succeeded, {@code false} otherwise
   1382      *
   1383      * Multicast filtering rules work as follows:
   1384      *
   1385      * The driver can filter multicast (v4 and/or v6) and broadcast packets when in
   1386      * a power optimized mode (typically when screen goes off).
   1387      *
   1388      * In order to prevent the driver from filtering the multicast/broadcast packets, we have to
   1389      * add a DRIVER RXFILTER-ADD rule followed by DRIVER RXFILTER-START to make the rule effective
   1390      *
   1391      * DRIVER RXFILTER-ADD Num
   1392      *   where Num = 0 - Unicast, 1 - Broadcast, 2 - Mutil4 or 3 - Multi6
   1393      *
   1394      * and DRIVER RXFILTER-START
   1395      * In order to stop the usage of these rules, we do
   1396      *
   1397      * DRIVER RXFILTER-STOP
   1398      * DRIVER RXFILTER-REMOVE Num
   1399      *   where Num is as described for RXFILTER-ADD
   1400      *
   1401      * The  SETSUSPENDOPT driver command overrides the filtering rules
   1402      */
   1403     public boolean startFilteringMulticastV4Packets(@NonNull String ifaceName) {
   1404         return mSupplicantStaIfaceHal.stopRxFilter(ifaceName)
   1405                 && mSupplicantStaIfaceHal.removeRxFilter(
   1406                         ifaceName, RX_FILTER_TYPE_V4_MULTICAST)
   1407                 && mSupplicantStaIfaceHal.startRxFilter(ifaceName);
   1408     }
   1409 
   1410     /**
   1411      * Stop filtering out Multicast V4 packets.
   1412      * @param ifaceName Name of the interface.
   1413      * @return {@code true} if the operation succeeded, {@code false} otherwise
   1414      */
   1415     public boolean stopFilteringMulticastV4Packets(@NonNull String ifaceName) {
   1416         return mSupplicantStaIfaceHal.stopRxFilter(ifaceName)
   1417                 && mSupplicantStaIfaceHal.addRxFilter(
   1418                         ifaceName, RX_FILTER_TYPE_V4_MULTICAST)
   1419                 && mSupplicantStaIfaceHal.startRxFilter(ifaceName);
   1420     }
   1421 
   1422     /**
   1423      * Start filtering out Multicast V6 packets
   1424      * @param ifaceName Name of the interface.
   1425      * @return {@code true} if the operation succeeded, {@code false} otherwise
   1426      */
   1427     public boolean startFilteringMulticastV6Packets(@NonNull String ifaceName) {
   1428         return mSupplicantStaIfaceHal.stopRxFilter(ifaceName)
   1429                 && mSupplicantStaIfaceHal.removeRxFilter(
   1430                         ifaceName, RX_FILTER_TYPE_V6_MULTICAST)
   1431                 && mSupplicantStaIfaceHal.startRxFilter(ifaceName);
   1432     }
   1433 
   1434     /**
   1435      * Stop filtering out Multicast V6 packets.
   1436      * @param ifaceName Name of the interface.
   1437      * @return {@code true} if the operation succeeded, {@code false} otherwise
   1438      */
   1439     public boolean stopFilteringMulticastV6Packets(@NonNull String ifaceName) {
   1440         return mSupplicantStaIfaceHal.stopRxFilter(ifaceName)
   1441                 && mSupplicantStaIfaceHal.addRxFilter(
   1442                         ifaceName, RX_FILTER_TYPE_V6_MULTICAST)
   1443                 && mSupplicantStaIfaceHal.startRxFilter(ifaceName);
   1444     }
   1445 
   1446     public static final int BLUETOOTH_COEXISTENCE_MODE_ENABLED  = 0;
   1447     public static final int BLUETOOTH_COEXISTENCE_MODE_DISABLED = 1;
   1448     public static final int BLUETOOTH_COEXISTENCE_MODE_SENSE    = 2;
   1449     /**
   1450      * Sets the bluetooth coexistence mode.
   1451      *
   1452      * @param ifaceName Name of the interface.
   1453      * @param mode One of {@link #BLUETOOTH_COEXISTENCE_MODE_DISABLED},
   1454      *            {@link #BLUETOOTH_COEXISTENCE_MODE_ENABLED}, or
   1455      *            {@link #BLUETOOTH_COEXISTENCE_MODE_SENSE}.
   1456      * @return Whether the mode was successfully set.
   1457      */
   1458     public boolean setBluetoothCoexistenceMode(@NonNull String ifaceName, int mode) {
   1459         return mSupplicantStaIfaceHal.setBtCoexistenceMode(ifaceName, mode);
   1460     }
   1461 
   1462     /**
   1463      * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
   1464      * some of the low-level scan parameters used by the driver are changed to
   1465      * reduce interference with A2DP streaming.
   1466      *
   1467      * @param ifaceName Name of the interface.
   1468      * @param setCoexScanMode whether to enable or disable this mode
   1469      * @return {@code true} if the command succeeded, {@code false} otherwise.
   1470      */
   1471     public boolean setBluetoothCoexistenceScanMode(
   1472             @NonNull String ifaceName, boolean setCoexScanMode) {
   1473         return mSupplicantStaIfaceHal.setBtCoexistenceScanModeEnabled(
   1474                 ifaceName, setCoexScanMode);
   1475     }
   1476 
   1477     /**
   1478      * Enable or disable suspend mode optimizations.
   1479      *
   1480      * @param ifaceName Name of the interface.
   1481      * @param enabled true to enable, false otherwise.
   1482      * @return true if request is sent successfully, false otherwise.
   1483      */
   1484     public boolean setSuspendOptimizations(@NonNull String ifaceName, boolean enabled) {
   1485         return mSupplicantStaIfaceHal.setSuspendModeEnabled(ifaceName, enabled);
   1486     }
   1487 
   1488     /**
   1489      * Set country code.
   1490      *
   1491      * @param ifaceName Name of the interface.
   1492      * @param countryCode 2 byte ASCII string. For ex: US, CA.
   1493      * @return true if request is sent successfully, false otherwise.
   1494      */
   1495     public boolean setCountryCode(@NonNull String ifaceName, String countryCode) {
   1496         return mSupplicantStaIfaceHal.setCountryCode(ifaceName, countryCode);
   1497     }
   1498 
   1499     /**
   1500      * Initiate TDLS discover and setup or teardown with the specified peer.
   1501      *
   1502      * @param ifaceName Name of the interface.
   1503      * @param macAddr MAC Address of the peer.
   1504      * @param enable true to start discovery and setup, false to teardown.
   1505      */
   1506     public void startTdls(@NonNull String ifaceName, String macAddr, boolean enable) {
   1507         if (enable) {
   1508             mSupplicantStaIfaceHal.initiateTdlsDiscover(ifaceName, macAddr);
   1509             mSupplicantStaIfaceHal.initiateTdlsSetup(ifaceName, macAddr);
   1510         } else {
   1511             mSupplicantStaIfaceHal.initiateTdlsTeardown(ifaceName, macAddr);
   1512         }
   1513     }
   1514 
   1515     /**
   1516      * Start WPS pin display operation with the specified peer.
   1517      *
   1518      * @param ifaceName Name of the interface.
   1519      * @param bssid BSSID of the peer.
   1520      * @return true if request is sent successfully, false otherwise.
   1521      */
   1522     public boolean startWpsPbc(@NonNull String ifaceName, String bssid) {
   1523         return mSupplicantStaIfaceHal.startWpsPbc(ifaceName, bssid);
   1524     }
   1525 
   1526     /**
   1527      * Start WPS pin keypad operation with the specified pin.
   1528      *
   1529      * @param ifaceName Name of the interface.
   1530      * @param pin Pin to be used.
   1531      * @return true if request is sent successfully, false otherwise.
   1532      */
   1533     public boolean startWpsPinKeypad(@NonNull String ifaceName, String pin) {
   1534         return mSupplicantStaIfaceHal.startWpsPinKeypad(ifaceName, pin);
   1535     }
   1536 
   1537     /**
   1538      * Start WPS pin display operation with the specified peer.
   1539      *
   1540      * @param ifaceName Name of the interface.
   1541      * @param bssid BSSID of the peer.
   1542      * @return new pin generated on success, null otherwise.
   1543      */
   1544     public String startWpsPinDisplay(@NonNull String ifaceName, String bssid) {
   1545         return mSupplicantStaIfaceHal.startWpsPinDisplay(ifaceName, bssid);
   1546     }
   1547 
   1548     /**
   1549      * Sets whether to use external sim for SIM/USIM processing.
   1550      *
   1551      * @param ifaceName Name of the interface.
   1552      * @param external true to enable, false otherwise.
   1553      * @return true if request is sent successfully, false otherwise.
   1554      */
   1555     public boolean setExternalSim(@NonNull String ifaceName, boolean external) {
   1556         return mSupplicantStaIfaceHal.setExternalSim(ifaceName, external);
   1557     }
   1558 
   1559     /**
   1560      * Sim auth response types.
   1561      */
   1562     public static final String SIM_AUTH_RESP_TYPE_GSM_AUTH = "GSM-AUTH";
   1563     public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTH = "UMTS-AUTH";
   1564     public static final String SIM_AUTH_RESP_TYPE_UMTS_AUTS = "UMTS-AUTS";
   1565 
   1566     /**
   1567      * EAP-SIM Error Codes
   1568      */
   1569     public static final int EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED = 16385;
   1570 
   1571     /**
   1572      * Send the sim auth response for the currently configured network.
   1573      *
   1574      * @param ifaceName Name of the interface.
   1575      * @param type |GSM-AUTH|, |UMTS-AUTH| or |UMTS-AUTS|.
   1576      * @param response Response params.
   1577      * @return true if succeeds, false otherwise.
   1578      */
   1579     public boolean simAuthResponse(
   1580             @NonNull String ifaceName, int id, String type, String response) {
   1581         if (SIM_AUTH_RESP_TYPE_GSM_AUTH.equals(type)) {
   1582             return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthResponse(
   1583                     ifaceName, response);
   1584         } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTH.equals(type)) {
   1585             return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthResponse(
   1586                     ifaceName, response);
   1587         } else if (SIM_AUTH_RESP_TYPE_UMTS_AUTS.equals(type)) {
   1588             return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAutsResponse(
   1589                     ifaceName, response);
   1590         } else {
   1591             return false;
   1592         }
   1593     }
   1594 
   1595     /**
   1596      * Send the eap sim gsm auth failure for the currently configured network.
   1597      *
   1598      * @param ifaceName Name of the interface.
   1599      * @return true if succeeds, false otherwise.
   1600      */
   1601     public boolean simAuthFailedResponse(@NonNull String ifaceName, int id) {
   1602         return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimGsmAuthFailure(ifaceName);
   1603     }
   1604 
   1605     /**
   1606      * Send the eap sim umts auth failure for the currently configured network.
   1607      *
   1608      * @param ifaceName Name of the interface.
   1609      * @return true if succeeds, false otherwise.
   1610      */
   1611     public boolean umtsAuthFailedResponse(@NonNull String ifaceName, int id) {
   1612         return mSupplicantStaIfaceHal.sendCurrentNetworkEapSimUmtsAuthFailure(ifaceName);
   1613     }
   1614 
   1615     /**
   1616      * Send the eap identity response for the currently configured network.
   1617      *
   1618      * @param ifaceName Name of the interface.
   1619      * @param unencryptedResponse String to send.
   1620      * @param encryptedResponse String to send.
   1621      * @return true if succeeds, false otherwise.
   1622      */
   1623     public boolean simIdentityResponse(@NonNull String ifaceName, int id,
   1624                                        String unencryptedResponse, String encryptedResponse) {
   1625         return mSupplicantStaIfaceHal.sendCurrentNetworkEapIdentityResponse(ifaceName,
   1626                 unencryptedResponse, encryptedResponse);
   1627     }
   1628 
   1629     /**
   1630      * This get anonymous identity from supplicant and returns it as a string.
   1631      *
   1632      * @param ifaceName Name of the interface.
   1633      * @return anonymous identity string if succeeds, null otherwise.
   1634      */
   1635     public String getEapAnonymousIdentity(@NonNull String ifaceName) {
   1636         return mSupplicantStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(ifaceName);
   1637     }
   1638 
   1639     /**
   1640      * Start WPS pin registrar operation with the specified peer and pin.
   1641      *
   1642      * @param ifaceName Name of the interface.
   1643      * @param bssid BSSID of the peer.
   1644      * @param pin Pin to be used.
   1645      * @return true if request is sent successfully, false otherwise.
   1646      */
   1647     public boolean startWpsRegistrar(@NonNull String ifaceName, String bssid, String pin) {
   1648         return mSupplicantStaIfaceHal.startWpsRegistrar(ifaceName, bssid, pin);
   1649     }
   1650 
   1651     /**
   1652      * Cancels any ongoing WPS requests.
   1653      *
   1654      * @param ifaceName Name of the interface.
   1655      * @return true if request is sent successfully, false otherwise.
   1656      */
   1657     public boolean cancelWps(@NonNull String ifaceName) {
   1658         return mSupplicantStaIfaceHal.cancelWps(ifaceName);
   1659     }
   1660 
   1661     /**
   1662      * Set WPS device name.
   1663      *
   1664      * @param ifaceName Name of the interface.
   1665      * @param name String to be set.
   1666      * @return true if request is sent successfully, false otherwise.
   1667      */
   1668     public boolean setDeviceName(@NonNull String ifaceName, String name) {
   1669         return mSupplicantStaIfaceHal.setWpsDeviceName(ifaceName, name);
   1670     }
   1671 
   1672     /**
   1673      * Set WPS device type.
   1674      *
   1675      * @param ifaceName Name of the interface.
   1676      * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg>
   1677      * @return true if request is sent successfully, false otherwise.
   1678      */
   1679     public boolean setDeviceType(@NonNull String ifaceName, String type) {
   1680         return mSupplicantStaIfaceHal.setWpsDeviceType(ifaceName, type);
   1681     }
   1682 
   1683     /**
   1684      * Set WPS config methods
   1685      *
   1686      * @param cfg List of config methods.
   1687      * @return true if request is sent successfully, false otherwise.
   1688      */
   1689     public boolean setConfigMethods(@NonNull String ifaceName, String cfg) {
   1690         return mSupplicantStaIfaceHal.setWpsConfigMethods(ifaceName, cfg);
   1691     }
   1692 
   1693     /**
   1694      * Set WPS manufacturer.
   1695      *
   1696      * @param ifaceName Name of the interface.
   1697      * @param value String to be set.
   1698      * @return true if request is sent successfully, false otherwise.
   1699      */
   1700     public boolean setManufacturer(@NonNull String ifaceName, String value) {
   1701         return mSupplicantStaIfaceHal.setWpsManufacturer(ifaceName, value);
   1702     }
   1703 
   1704     /**
   1705      * Set WPS model name.
   1706      *
   1707      * @param ifaceName Name of the interface.
   1708      * @param value String to be set.
   1709      * @return true if request is sent successfully, false otherwise.
   1710      */
   1711     public boolean setModelName(@NonNull String ifaceName, String value) {
   1712         return mSupplicantStaIfaceHal.setWpsModelName(ifaceName, value);
   1713     }
   1714 
   1715     /**
   1716      * Set WPS model number.
   1717      *
   1718      * @param ifaceName Name of the interface.
   1719      * @param value String to be set.
   1720      * @return true if request is sent successfully, false otherwise.
   1721      */
   1722     public boolean setModelNumber(@NonNull String ifaceName, String value) {
   1723         return mSupplicantStaIfaceHal.setWpsModelNumber(ifaceName, value);
   1724     }
   1725 
   1726     /**
   1727      * Set WPS serial number.
   1728      *
   1729      * @param ifaceName Name of the interface.
   1730      * @param value String to be set.
   1731      * @return true if request is sent successfully, false otherwise.
   1732      */
   1733     public boolean setSerialNumber(@NonNull String ifaceName, String value) {
   1734         return mSupplicantStaIfaceHal.setWpsSerialNumber(ifaceName, value);
   1735     }
   1736 
   1737     /**
   1738      * Enable or disable power save mode.
   1739      *
   1740      * @param ifaceName Name of the interface.
   1741      * @param enabled true to enable, false to disable.
   1742      */
   1743     public void setPowerSave(@NonNull String ifaceName, boolean enabled) {
   1744         mSupplicantStaIfaceHal.setPowerSave(ifaceName, enabled);
   1745     }
   1746 
   1747     /**
   1748      * Set concurrency priority between P2P & STA operations.
   1749      *
   1750      * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations,
   1751      *                            false otherwise.
   1752      * @return true if request is sent successfully, false otherwise.
   1753      */
   1754     public boolean setConcurrencyPriority(boolean isStaHigherPriority) {
   1755         return mSupplicantStaIfaceHal.setConcurrencyPriority(isStaHigherPriority);
   1756     }
   1757 
   1758     /**
   1759      * Enable/Disable auto reconnect functionality in wpa_supplicant.
   1760      *
   1761      * @param ifaceName Name of the interface.
   1762      * @param enable true to enable auto reconnecting, false to disable.
   1763      * @return true if request is sent successfully, false otherwise.
   1764      */
   1765     public boolean enableStaAutoReconnect(@NonNull String ifaceName, boolean enable) {
   1766         return mSupplicantStaIfaceHal.enableAutoReconnect(ifaceName, enable);
   1767     }
   1768 
   1769     /**
   1770      * Migrate all the configured networks from wpa_supplicant.
   1771      *
   1772      * @param ifaceName Name of the interface.
   1773      * @param configs       Map of configuration key to configuration objects corresponding to all
   1774      *                      the networks.
   1775      * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf
   1776      * @return Max priority of all the configs.
   1777      */
   1778     public boolean migrateNetworksFromSupplicant(
   1779             @NonNull String ifaceName, Map<String, WifiConfiguration> configs,
   1780             SparseArray<Map<String, String>> networkExtras) {
   1781         return mSupplicantStaIfaceHal.loadNetworks(ifaceName, configs, networkExtras);
   1782     }
   1783 
   1784     /**
   1785      * Add the provided network configuration to wpa_supplicant and initiate connection to it.
   1786      * This method does the following:
   1787      * 1. Abort any ongoing scan to unblock the connection request.
   1788      * 2. Remove any existing network in wpa_supplicant(This implicitly triggers disconnect).
   1789      * 3. Add a new network to wpa_supplicant.
   1790      * 4. Save the provided configuration to wpa_supplicant.
   1791      * 5. Select the new network in wpa_supplicant.
   1792      * 6. Triggers reconnect command to wpa_supplicant.
   1793      *
   1794      * @param ifaceName Name of the interface.
   1795      * @param configuration WifiConfiguration parameters for the provided network.
   1796      * @return {@code true} if it succeeds, {@code false} otherwise
   1797      */
   1798     public boolean connectToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) {
   1799         // Abort ongoing scan before connect() to unblock connection request.
   1800         mWificondControl.abortScan(ifaceName);
   1801         return mSupplicantStaIfaceHal.connectToNetwork(ifaceName, configuration);
   1802     }
   1803 
   1804     /**
   1805      * Initiates roaming to the already configured network in wpa_supplicant. If the network
   1806      * configuration provided does not match the already configured network, then this triggers
   1807      * a new connection attempt (instead of roam).
   1808      * 1. Abort any ongoing scan to unblock the roam request.
   1809      * 2. First check if we're attempting to connect to the same network as we currently have
   1810      * configured.
   1811      * 3. Set the new bssid for the network in wpa_supplicant.
   1812      * 4. Triggers reassociate command to wpa_supplicant.
   1813      *
   1814      * @param ifaceName Name of the interface.
   1815      * @param configuration WifiConfiguration parameters for the provided network.
   1816      * @return {@code true} if it succeeds, {@code false} otherwise
   1817      */
   1818     public boolean roamToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) {
   1819         // Abort ongoing scan before connect() to unblock roaming request.
   1820         mWificondControl.abortScan(ifaceName);
   1821         return mSupplicantStaIfaceHal.roamToNetwork(ifaceName, configuration);
   1822     }
   1823 
   1824     /**
   1825      * Remove all the networks.
   1826      *
   1827      * @param ifaceName Name of the interface.
   1828      * @return {@code true} if it succeeds, {@code false} otherwise
   1829      */
   1830     public boolean removeAllNetworks(@NonNull String ifaceName) {
   1831         return mSupplicantStaIfaceHal.removeAllNetworks(ifaceName);
   1832     }
   1833 
   1834     /**
   1835      * Set the BSSID for the currently configured network in wpa_supplicant.
   1836      *
   1837      * @param ifaceName Name of the interface.
   1838      * @return true if successful, false otherwise.
   1839      */
   1840     public boolean setConfiguredNetworkBSSID(@NonNull String ifaceName, String bssid) {
   1841         return mSupplicantStaIfaceHal.setCurrentNetworkBssid(ifaceName, bssid);
   1842     }
   1843 
   1844     /**
   1845      * Initiate ANQP query.
   1846      *
   1847      * @param ifaceName Name of the interface.
   1848      * @param bssid BSSID of the AP to be queried
   1849      * @param anqpIds Set of anqp IDs.
   1850      * @param hs20Subtypes Set of HS20 subtypes.
   1851      * @return true on success, false otherwise.
   1852      */
   1853     public boolean requestAnqp(
   1854             @NonNull String ifaceName, String bssid, Set<Integer> anqpIds,
   1855             Set<Integer> hs20Subtypes) {
   1856         if (bssid == null || ((anqpIds == null || anqpIds.isEmpty())
   1857                 && (hs20Subtypes == null || hs20Subtypes.isEmpty()))) {
   1858             Log.e(TAG, "Invalid arguments for ANQP request.");
   1859             return false;
   1860         }
   1861         ArrayList<Short> anqpIdList = new ArrayList<>();
   1862         for (Integer anqpId : anqpIds) {
   1863             anqpIdList.add(anqpId.shortValue());
   1864         }
   1865         ArrayList<Integer> hs20SubtypeList = new ArrayList<>();
   1866         hs20SubtypeList.addAll(hs20Subtypes);
   1867         return mSupplicantStaIfaceHal.initiateAnqpQuery(
   1868                 ifaceName, bssid, anqpIdList, hs20SubtypeList);
   1869     }
   1870 
   1871     /**
   1872      * Request a passpoint icon file |filename| from the specified AP |bssid|.
   1873      *
   1874      * @param ifaceName Name of the interface.
   1875      * @param bssid BSSID of the AP
   1876      * @param fileName name of the icon file
   1877      * @return true if request is sent successfully, false otherwise
   1878      */
   1879     public boolean requestIcon(@NonNull String ifaceName, String  bssid, String fileName) {
   1880         if (bssid == null || fileName == null) {
   1881             Log.e(TAG, "Invalid arguments for Icon request.");
   1882             return false;
   1883         }
   1884         return mSupplicantStaIfaceHal.initiateHs20IconQuery(ifaceName, bssid, fileName);
   1885     }
   1886 
   1887     /**
   1888      * Get the currently configured network's WPS NFC token.
   1889      *
   1890      * @param ifaceName Name of the interface.
   1891      * @return Hex string corresponding to the WPS NFC token.
   1892      */
   1893     public String getCurrentNetworkWpsNfcConfigurationToken(@NonNull String ifaceName) {
   1894         return mSupplicantStaIfaceHal.getCurrentNetworkWpsNfcConfigurationToken(ifaceName);
   1895     }
   1896 
   1897     /** Remove the request |networkId| from supplicant if it's the current network,
   1898      * if the current configured network matches |networkId|.
   1899      *
   1900      * @param ifaceName Name of the interface.
   1901      * @param networkId network id of the network to be removed from supplicant.
   1902      */
   1903     public void removeNetworkIfCurrent(@NonNull String ifaceName, int networkId) {
   1904         mSupplicantStaIfaceHal.removeNetworkIfCurrent(ifaceName, networkId);
   1905     }
   1906 
   1907     /********************************************************
   1908      * Vendor HAL operations
   1909      ********************************************************/
   1910     /**
   1911      * Callback to notify vendor HAL death.
   1912      */
   1913     public interface VendorHalDeathEventHandler {
   1914         /**
   1915          * Invoked when the vendor HAL dies.
   1916          */
   1917         void onDeath();
   1918     }
   1919 
   1920     /**
   1921      * Callback to notify when vendor HAL detects that a change in radio mode.
   1922      */
   1923     public interface VendorHalRadioModeChangeEventHandler {
   1924         /**
   1925          * Invoked when the vendor HAL detects a change to MCC mode.
   1926          * MCC (Multi channel concurrency) = Multiple interfaces are active on the same band,
   1927          * different channels, same radios.
   1928          *
   1929          * @param band Band on which MCC is detected (specified by one of the
   1930          *             WifiScanner.WIFI_BAND_* constants)
   1931          */
   1932         void onMcc(int band);
   1933         /**
   1934          * Invoked when the vendor HAL detects a change to SCC mode.
   1935          * SCC (Single channel concurrency) = Multiple interfaces are active on the same band, same
   1936          * channels, same radios.
   1937          *
   1938          * @param band Band on which SCC is detected (specified by one of the
   1939          *             WifiScanner.WIFI_BAND_* constants)
   1940          */
   1941         void onScc(int band);
   1942         /**
   1943          * Invoked when the vendor HAL detects a change to SBS mode.
   1944          * SBS (Single Band Simultaneous) = Multiple interfaces are active on the same band,
   1945          * different channels, different radios.
   1946          *
   1947          * @param band Band on which SBS is detected (specified by one of the
   1948          *             WifiScanner.WIFI_BAND_* constants)
   1949          */
   1950         void onSbs(int band);
   1951         /**
   1952          * Invoked when the vendor HAL detects a change to DBS mode.
   1953          * DBS (Dual Band Simultaneous) = Multiple interfaces are active on the different bands,
   1954          * different channels, different radios.
   1955          */
   1956         void onDbs();
   1957     }
   1958 
   1959     /**
   1960      * Tests whether the HAL is running or not
   1961      */
   1962     public boolean isHalStarted() {
   1963         return mWifiVendorHal.isHalStarted();
   1964     }
   1965 
   1966     // TODO: Change variable names to camel style.
   1967     public static class ScanCapabilities {
   1968         public int  max_scan_cache_size;
   1969         public int  max_scan_buckets;
   1970         public int  max_ap_cache_per_scan;
   1971         public int  max_rssi_sample_size;
   1972         public int  max_scan_reporting_threshold;
   1973     }
   1974 
   1975     /**
   1976      * Gets the scan capabilities
   1977      *
   1978      * @param ifaceName Name of the interface.
   1979      * @param capabilities object to be filled in
   1980      * @return true for success. false for failure
   1981      */
   1982     public boolean getBgScanCapabilities(
   1983             @NonNull String ifaceName, ScanCapabilities capabilities) {
   1984         return mWifiVendorHal.getBgScanCapabilities(ifaceName, capabilities);
   1985     }
   1986 
   1987     public static class ChannelSettings {
   1988         public int frequency;
   1989         public int dwell_time_ms;
   1990         public boolean passive;
   1991     }
   1992 
   1993     public static class BucketSettings {
   1994         public int bucket;
   1995         public int band;
   1996         public int period_ms;
   1997         public int max_period_ms;
   1998         public int step_count;
   1999         public int report_events;
   2000         public int num_channels;
   2001         public ChannelSettings[] channels;
   2002     }
   2003 
   2004     /**
   2005      * Network parameters for hidden networks to be scanned for.
   2006      */
   2007     public static class HiddenNetwork {
   2008         public String ssid;
   2009 
   2010         @Override
   2011         public boolean equals(Object otherObj) {
   2012             if (this == otherObj) {
   2013                 return true;
   2014             } else if (otherObj == null || getClass() != otherObj.getClass()) {
   2015                 return false;
   2016             }
   2017             HiddenNetwork other = (HiddenNetwork) otherObj;
   2018             return Objects.equals(ssid, other.ssid);
   2019         }
   2020 
   2021         @Override
   2022         public int hashCode() {
   2023             return (ssid == null ? 0 : ssid.hashCode());
   2024         }
   2025     }
   2026 
   2027     public static final int SCAN_TYPE_LOW_LATENCY = 0;
   2028     public static final int SCAN_TYPE_LOW_POWER = 1;
   2029     public static final int SCAN_TYPE_HIGH_ACCURACY = 2;
   2030 
   2031     public static class ScanSettings {
   2032         /**
   2033          * Type of scan to perform. One of {@link ScanSettings#SCAN_TYPE_LOW_LATENCY},
   2034          * {@link ScanSettings#SCAN_TYPE_LOW_POWER} or {@link ScanSettings#SCAN_TYPE_HIGH_ACCURACY}.
   2035          */
   2036         public int scanType;
   2037         public int base_period_ms;
   2038         public int max_ap_per_scan;
   2039         public int report_threshold_percent;
   2040         public int report_threshold_num_scans;
   2041         public int num_buckets;
   2042         /* Not used for bg scans. Only works for single scans. */
   2043         public HiddenNetwork[] hiddenNetworks;
   2044         public BucketSettings[] buckets;
   2045     }
   2046 
   2047     /**
   2048      * Network parameters to start PNO scan.
   2049      */
   2050     public static class PnoNetwork {
   2051         public String ssid;
   2052         public byte flags;
   2053         public byte auth_bit_field;
   2054 
   2055         @Override
   2056         public boolean equals(Object otherObj) {
   2057             if (this == otherObj) {
   2058                 return true;
   2059             } else if (otherObj == null || getClass() != otherObj.getClass()) {
   2060                 return false;
   2061             }
   2062             PnoNetwork other = (PnoNetwork) otherObj;
   2063             return ((Objects.equals(ssid, other.ssid)) && (flags == other.flags)
   2064                     && (auth_bit_field == other.auth_bit_field));
   2065         }
   2066 
   2067         @Override
   2068         public int hashCode() {
   2069             int result = (ssid == null ? 0 : ssid.hashCode());
   2070             result ^= ((int) flags * 31) + ((int) auth_bit_field << 8);
   2071             return result;
   2072         }
   2073     }
   2074 
   2075     /**
   2076      * Parameters to start PNO scan. This holds the list of networks which are going to used for
   2077      * PNO scan.
   2078      */
   2079     public static class PnoSettings {
   2080         public int min5GHzRssi;
   2081         public int min24GHzRssi;
   2082         public int initialScoreMax;
   2083         public int currentConnectionBonus;
   2084         public int sameNetworkBonus;
   2085         public int secureBonus;
   2086         public int band5GHzBonus;
   2087         public int periodInMs;
   2088         public boolean isConnected;
   2089         public PnoNetwork[] networkList;
   2090     }
   2091 
   2092     public static interface ScanEventHandler {
   2093         /**
   2094          * Called for each AP as it is found with the entire contents of the beacon/probe response.
   2095          * Only called when WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT is specified.
   2096          */
   2097         void onFullScanResult(ScanResult fullScanResult, int bucketsScanned);
   2098         /**
   2099          * Callback on an event during a gscan scan.
   2100          * See WifiNative.WIFI_SCAN_* for possible values.
   2101          */
   2102         void onScanStatus(int event);
   2103         /**
   2104          * Called with the current cached scan results when gscan is paused.
   2105          */
   2106         void onScanPaused(WifiScanner.ScanData[] data);
   2107         /**
   2108          * Called with the current cached scan results when gscan is resumed.
   2109          */
   2110         void onScanRestarted();
   2111     }
   2112 
   2113     /**
   2114      * Handler to notify the occurrence of various events during PNO scan.
   2115      */
   2116     public interface PnoEventHandler {
   2117         /**
   2118          * Callback to notify when one of the shortlisted networks is found during PNO scan.
   2119          * @param results List of Scan results received.
   2120          */
   2121         void onPnoNetworkFound(ScanResult[] results);
   2122 
   2123         /**
   2124          * Callback to notify when the PNO scan schedule fails.
   2125          */
   2126         void onPnoScanFailed();
   2127     }
   2128 
   2129     public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0;
   2130     public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1;
   2131     public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2;
   2132     public static final int WIFI_SCAN_FAILED = 3;
   2133 
   2134     /**
   2135      * Starts a background scan.
   2136      * Any ongoing scan will be stopped first
   2137      *
   2138      * @param ifaceName Name of the interface.
   2139      * @param settings     to control the scan
   2140      * @param eventHandler to call with the results
   2141      * @return true for success
   2142      */
   2143     public boolean startBgScan(
   2144             @NonNull String ifaceName, ScanSettings settings, ScanEventHandler eventHandler) {
   2145         return mWifiVendorHal.startBgScan(ifaceName, settings, eventHandler);
   2146     }
   2147 
   2148     /**
   2149      * Stops any ongoing backgound scan
   2150      * @param ifaceName Name of the interface.
   2151      */
   2152     public void stopBgScan(@NonNull String ifaceName) {
   2153         mWifiVendorHal.stopBgScan(ifaceName);
   2154     }
   2155 
   2156     /**
   2157      * Pauses an ongoing backgound scan
   2158      * @param ifaceName Name of the interface.
   2159      */
   2160     public void pauseBgScan(@NonNull String ifaceName) {
   2161         mWifiVendorHal.pauseBgScan(ifaceName);
   2162     }
   2163 
   2164     /**
   2165      * Restarts a paused scan
   2166      * @param ifaceName Name of the interface.
   2167      */
   2168     public void restartBgScan(@NonNull String ifaceName) {
   2169         mWifiVendorHal.restartBgScan(ifaceName);
   2170     }
   2171 
   2172     /**
   2173      * Gets the latest scan results received.
   2174      * @param ifaceName Name of the interface.
   2175      */
   2176     public WifiScanner.ScanData[] getBgScanResults(@NonNull String ifaceName) {
   2177         return mWifiVendorHal.getBgScanResults(ifaceName);
   2178     }
   2179 
   2180     /**
   2181      * Gets the latest link layer stats
   2182      * @param ifaceName Name of the interface.
   2183      */
   2184     public WifiLinkLayerStats getWifiLinkLayerStats(@NonNull String ifaceName) {
   2185         return mWifiVendorHal.getWifiLinkLayerStats(ifaceName);
   2186     }
   2187 
   2188     /**
   2189      * Get the supported features
   2190      *
   2191      * @param ifaceName Name of the interface.
   2192      * @return bitmask defined by WifiManager.WIFI_FEATURE_*
   2193      */
   2194     public int getSupportedFeatureSet(@NonNull String ifaceName) {
   2195         return mWifiVendorHal.getSupportedFeatureSet(ifaceName);
   2196     }
   2197 
   2198     public static interface RttEventHandler {
   2199         void onRttResults(RttManager.RttResult[] result);
   2200     }
   2201 
   2202     /**
   2203      * Starts a new rtt request
   2204      *
   2205      * @param params RTT request params. Refer to {@link RttManager#RttParams}.
   2206      * @param handler Callback to be invoked to notify any results.
   2207      * @return true if the request was successful, false otherwise.
   2208      */
   2209     public boolean requestRtt(
   2210             RttManager.RttParams[] params, RttEventHandler handler) {
   2211         return mWifiVendorHal.requestRtt(params, handler);
   2212     }
   2213 
   2214     /**
   2215      * Cancels an outstanding rtt request
   2216      *
   2217      * @param params RTT request params. Refer to {@link RttManager#RttParams}
   2218      * @return true if there was an outstanding request and it was successfully cancelled
   2219      */
   2220     public boolean cancelRtt(RttManager.RttParams[] params) {
   2221         return mWifiVendorHal.cancelRtt(params);
   2222     }
   2223 
   2224     /**
   2225      * Enable RTT responder role on the device. Returns {@link ResponderConfig} if the responder
   2226      * role is successfully enabled, {@code null} otherwise.
   2227      *
   2228      * @param timeoutSeconds timeout to use for the responder.
   2229      */
   2230     @Nullable
   2231     public ResponderConfig enableRttResponder(int timeoutSeconds) {
   2232         return mWifiVendorHal.enableRttResponder(timeoutSeconds);
   2233     }
   2234 
   2235     /**
   2236      * Disable RTT responder role. Returns {@code true} if responder role is successfully disabled,
   2237      * {@code false} otherwise.
   2238      */
   2239     public boolean disableRttResponder() {
   2240         return mWifiVendorHal.disableRttResponder();
   2241     }
   2242 
   2243     /**
   2244      * Set the MAC OUI during scanning.
   2245      * An OUI {Organizationally Unique Identifier} is a 24-bit number that
   2246      * uniquely identifies a vendor or manufacturer.
   2247      *
   2248      * @param ifaceName Name of the interface.
   2249      * @param oui OUI to set.
   2250      * @return true for success
   2251      */
   2252     public boolean setScanningMacOui(@NonNull String ifaceName, byte[] oui) {
   2253         return mWifiVendorHal.setScanningMacOui(ifaceName, oui);
   2254     }
   2255 
   2256     /**
   2257      * RTT (Round Trip Time) measurement capabilities of the device.
   2258      */
   2259     public RttManager.RttCapabilities getRttCapabilities() {
   2260         return mWifiVendorHal.getRttCapabilities();
   2261     }
   2262 
   2263     /**
   2264      * Get the APF (Android Packet Filter) capabilities of the device
   2265      * @param ifaceName Name of the interface.
   2266      */
   2267     public ApfCapabilities getApfCapabilities(@NonNull String ifaceName) {
   2268         return mWifiVendorHal.getApfCapabilities(ifaceName);
   2269     }
   2270 
   2271     /**
   2272      * Installs an APF program on this iface, replacing any existing program.
   2273      *
   2274      * @param ifaceName Name of the interface
   2275      * @param filter is the android packet filter program
   2276      * @return true for success
   2277      */
   2278     public boolean installPacketFilter(@NonNull String ifaceName, byte[] filter) {
   2279         return mWifiVendorHal.installPacketFilter(ifaceName, filter);
   2280     }
   2281 
   2282     /**
   2283      * Reads the APF program and data buffer for this iface.
   2284      *
   2285      * @param ifaceName Name of the interface
   2286      * @return the buffer returned by the driver, or null in case of an error
   2287      */
   2288     public byte[] readPacketFilter(@NonNull String ifaceName) {
   2289         return mWifiVendorHal.readPacketFilter(ifaceName);
   2290     }
   2291 
   2292     /**
   2293      * Set country code for this AP iface.
   2294      * @param ifaceName Name of the interface.
   2295      * @param countryCode - two-letter country code (as ISO 3166)
   2296      * @return true for success
   2297      */
   2298     public boolean setCountryCodeHal(@NonNull String ifaceName, String countryCode) {
   2299         return mWifiVendorHal.setCountryCodeHal(ifaceName, countryCode);
   2300     }
   2301 
   2302     //---------------------------------------------------------------------------------
   2303     /* Wifi Logger commands/events */
   2304     public static interface WifiLoggerEventHandler {
   2305         void onRingBufferData(RingBufferStatus status, byte[] buffer);
   2306         void onWifiAlert(int errorCode, byte[] buffer);
   2307     }
   2308 
   2309     /**
   2310      * Registers the logger callback and enables alerts.
   2311      * Ring buffer data collection is only triggered when |startLoggingRingBuffer| is invoked.
   2312      *
   2313      * @param handler Callback to be invoked.
   2314      * @return true on success, false otherwise.
   2315      */
   2316     public boolean setLoggingEventHandler(WifiLoggerEventHandler handler) {
   2317         return mWifiVendorHal.setLoggingEventHandler(handler);
   2318     }
   2319 
   2320     /**
   2321      * Control debug data collection
   2322      *
   2323      * @param verboseLevel 0 to 3, inclusive. 0 stops logging.
   2324      * @param flags        Ignored.
   2325      * @param maxInterval  Maximum interval between reports; ignore if 0.
   2326      * @param minDataSize  Minimum data size in buffer for report; ignore if 0.
   2327      * @param ringName     Name of the ring for which data collection is to start.
   2328      * @return true for success, false otherwise.
   2329      */
   2330     public boolean startLoggingRingBuffer(int verboseLevel, int flags, int maxInterval,
   2331             int minDataSize, String ringName){
   2332         return mWifiVendorHal.startLoggingRingBuffer(
   2333                 verboseLevel, flags, maxInterval, minDataSize, ringName);
   2334     }
   2335 
   2336     /**
   2337      * Logger features exposed.
   2338      * This is a no-op now, will always return -1.
   2339      *
   2340      * @return true on success, false otherwise.
   2341      */
   2342     public int getSupportedLoggerFeatureSet() {
   2343         return mWifiVendorHal.getSupportedLoggerFeatureSet();
   2344     }
   2345 
   2346     /**
   2347      * Stops all logging and resets the logger callback.
   2348      * This stops both the alerts and ring buffer data collection.
   2349      * @return true on success, false otherwise.
   2350      */
   2351     public boolean resetLogHandler() {
   2352         return mWifiVendorHal.resetLogHandler();
   2353     }
   2354 
   2355     /**
   2356      * Vendor-provided wifi driver version string
   2357      *
   2358      * @return String returned from the HAL.
   2359      */
   2360     public String getDriverVersion() {
   2361         return mWifiVendorHal.getDriverVersion();
   2362     }
   2363 
   2364     /**
   2365      * Vendor-provided wifi firmware version string
   2366      *
   2367      * @return String returned from the HAL.
   2368      */
   2369     public String getFirmwareVersion() {
   2370         return mWifiVendorHal.getFirmwareVersion();
   2371     }
   2372 
   2373     public static class RingBufferStatus{
   2374         String name;
   2375         int flag;
   2376         int ringBufferId;
   2377         int ringBufferByteSize;
   2378         int verboseLevel;
   2379         int writtenBytes;
   2380         int readBytes;
   2381         int writtenRecords;
   2382 
   2383         // Bit masks for interpreting |flag|
   2384         public static final int HAS_BINARY_ENTRIES = (1 << 0);
   2385         public static final int HAS_ASCII_ENTRIES = (1 << 1);
   2386         public static final int HAS_PER_PACKET_ENTRIES = (1 << 2);
   2387 
   2388         @Override
   2389         public String toString() {
   2390             return "name: " + name + " flag: " + flag + " ringBufferId: " + ringBufferId +
   2391                     " ringBufferByteSize: " +ringBufferByteSize + " verboseLevel: " +verboseLevel +
   2392                     " writtenBytes: " + writtenBytes + " readBytes: " + readBytes +
   2393                     " writtenRecords: " + writtenRecords;
   2394         }
   2395     }
   2396 
   2397     /**
   2398      * API to get the status of all ring buffers supported by driver
   2399      */
   2400     public RingBufferStatus[] getRingBufferStatus() {
   2401         return mWifiVendorHal.getRingBufferStatus();
   2402     }
   2403 
   2404     /**
   2405      * Indicates to driver that all the data has to be uploaded urgently
   2406      *
   2407      * @param ringName Name of the ring buffer requested.
   2408      * @return true on success, false otherwise.
   2409      */
   2410     public boolean getRingBufferData(String ringName) {
   2411         return mWifiVendorHal.getRingBufferData(ringName);
   2412     }
   2413 
   2414     /**
   2415      * Request vendor debug info from the firmware
   2416      *
   2417      * @return Raw data obtained from the HAL.
   2418      */
   2419     public byte[] getFwMemoryDump() {
   2420         return mWifiVendorHal.getFwMemoryDump();
   2421     }
   2422 
   2423     /**
   2424      * Request vendor debug info from the driver
   2425      *
   2426      * @return Raw data obtained from the HAL.
   2427      */
   2428     public byte[] getDriverStateDump() {
   2429         return mWifiVendorHal.getDriverStateDump();
   2430     }
   2431 
   2432     //---------------------------------------------------------------------------------
   2433     /* Packet fate API */
   2434 
   2435     @Immutable
   2436     abstract static class FateReport {
   2437         final static int USEC_PER_MSEC = 1000;
   2438         // The driver timestamp is a 32-bit counter, in microseconds. This field holds the
   2439         // maximal value of a driver timestamp in milliseconds.
   2440         final static int MAX_DRIVER_TIMESTAMP_MSEC = (int) (0xffffffffL / 1000);
   2441         final static SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss.SSS");
   2442 
   2443         final byte mFate;
   2444         final long mDriverTimestampUSec;
   2445         final byte mFrameType;
   2446         final byte[] mFrameBytes;
   2447         final long mEstimatedWallclockMSec;
   2448 
   2449         FateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
   2450             mFate = fate;
   2451             mDriverTimestampUSec = driverTimestampUSec;
   2452             mEstimatedWallclockMSec =
   2453                     convertDriverTimestampUSecToWallclockMSec(mDriverTimestampUSec);
   2454             mFrameType = frameType;
   2455             mFrameBytes = frameBytes;
   2456         }
   2457 
   2458         public String toTableRowString() {
   2459             StringWriter sw = new StringWriter();
   2460             PrintWriter pw = new PrintWriter(sw);
   2461             FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
   2462             dateFormatter.setTimeZone(TimeZone.getDefault());
   2463             pw.format("%-15s  %12s  %-9s  %-32s  %-12s  %-23s  %s\n",
   2464                     mDriverTimestampUSec,
   2465                     dateFormatter.format(new Date(mEstimatedWallclockMSec)),
   2466                     directionToString(), fateToString(), parser.mMostSpecificProtocolString,
   2467                     parser.mTypeString, parser.mResultString);
   2468             return sw.toString();
   2469         }
   2470 
   2471         public String toVerboseStringWithPiiAllowed() {
   2472             StringWriter sw = new StringWriter();
   2473             PrintWriter pw = new PrintWriter(sw);
   2474             FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
   2475             pw.format("Frame direction: %s\n", directionToString());
   2476             pw.format("Frame timestamp: %d\n", mDriverTimestampUSec);
   2477             pw.format("Frame fate: %s\n", fateToString());
   2478             pw.format("Frame type: %s\n", frameTypeToString(mFrameType));
   2479             pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString);
   2480             pw.format("Frame protocol type: %s\n", parser.mTypeString);
   2481             pw.format("Frame length: %d\n", mFrameBytes.length);
   2482             pw.append("Frame bytes");
   2483             pw.append(HexDump.dumpHexString(mFrameBytes));  // potentially contains PII
   2484             pw.append("\n");
   2485             return sw.toString();
   2486         }
   2487 
   2488         /* Returns a header to match the output of toTableRowString(). */
   2489         public static String getTableHeader() {
   2490             StringWriter sw = new StringWriter();
   2491             PrintWriter pw = new PrintWriter(sw);
   2492             pw.format("\n%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
   2493                     "Time usec", "Walltime", "Direction", "Fate", "Protocol", "Type", "Result");
   2494             pw.format("%-15s  %-12s  %-9s  %-32s  %-12s  %-23s  %s\n",
   2495                     "---------", "--------", "---------", "----", "--------", "----", "------");
   2496             return sw.toString();
   2497         }
   2498 
   2499         protected abstract String directionToString();
   2500 
   2501         protected abstract String fateToString();
   2502 
   2503         private static String frameTypeToString(byte frameType) {
   2504             switch (frameType) {
   2505                 case WifiLoggerHal.FRAME_TYPE_UNKNOWN:
   2506                     return "unknown";
   2507                 case WifiLoggerHal.FRAME_TYPE_ETHERNET_II:
   2508                     return "data";
   2509                 case WifiLoggerHal.FRAME_TYPE_80211_MGMT:
   2510                     return "802.11 management";
   2511                 default:
   2512                     return Byte.toString(frameType);
   2513             }
   2514         }
   2515 
   2516         /**
   2517          * Converts a driver timestamp to a wallclock time, based on the current
   2518          * BOOTTIME to wallclock mapping. The driver timestamp is a 32-bit counter of
   2519          * microseconds, with the same base as BOOTTIME.
   2520          */
   2521         private static long convertDriverTimestampUSecToWallclockMSec(long driverTimestampUSec) {
   2522             final long wallclockMillisNow = System.currentTimeMillis();
   2523             final long boottimeMillisNow = SystemClock.elapsedRealtime();
   2524             final long driverTimestampMillis = driverTimestampUSec / USEC_PER_MSEC;
   2525 
   2526             long boottimeTimestampMillis = boottimeMillisNow % MAX_DRIVER_TIMESTAMP_MSEC;
   2527             if (boottimeTimestampMillis < driverTimestampMillis) {
   2528                 // The 32-bit microsecond count has wrapped between the time that the driver
   2529                 // recorded the packet, and the call to this function. Adjust the BOOTTIME
   2530                 // timestamp, to compensate.
   2531                 //
   2532                 // Note that overflow is not a concern here, since the result is less than
   2533                 // 2 * MAX_DRIVER_TIMESTAMP_MSEC. (Given the modulus operation above,
   2534                 // boottimeTimestampMillis must be less than MAX_DRIVER_TIMESTAMP_MSEC.) And, since
   2535                 // MAX_DRIVER_TIMESTAMP_MSEC is an int, 2 * MAX_DRIVER_TIMESTAMP_MSEC must fit
   2536                 // within a long.
   2537                 boottimeTimestampMillis += MAX_DRIVER_TIMESTAMP_MSEC;
   2538             }
   2539 
   2540             final long millisSincePacketTimestamp = boottimeTimestampMillis - driverTimestampMillis;
   2541             return wallclockMillisNow - millisSincePacketTimestamp;
   2542         }
   2543     }
   2544 
   2545     /**
   2546      * Represents the fate information for one outbound packet.
   2547      */
   2548     @Immutable
   2549     public static final class TxFateReport extends FateReport {
   2550         TxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
   2551             super(fate, driverTimestampUSec, frameType, frameBytes);
   2552         }
   2553 
   2554         @Override
   2555         protected String directionToString() {
   2556             return "TX";
   2557         }
   2558 
   2559         @Override
   2560         protected String fateToString() {
   2561             switch (mFate) {
   2562                 case WifiLoggerHal.TX_PKT_FATE_ACKED:
   2563                     return "acked";
   2564                 case WifiLoggerHal.TX_PKT_FATE_SENT:
   2565                     return "sent";
   2566                 case WifiLoggerHal.TX_PKT_FATE_FW_QUEUED:
   2567                     return "firmware queued";
   2568                 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID:
   2569                     return "firmware dropped (invalid frame)";
   2570                 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS:
   2571                     return "firmware dropped (no bufs)";
   2572                 case WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER:
   2573                     return "firmware dropped (other)";
   2574                 case WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED:
   2575                     return "driver queued";
   2576                 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID:
   2577                     return "driver dropped (invalid frame)";
   2578                 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS:
   2579                     return "driver dropped (no bufs)";
   2580                 case WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER:
   2581                     return "driver dropped (other)";
   2582                 default:
   2583                     return Byte.toString(mFate);
   2584             }
   2585         }
   2586     }
   2587 
   2588     /**
   2589      * Represents the fate information for one inbound packet.
   2590      */
   2591     @Immutable
   2592     public static final class RxFateReport extends FateReport {
   2593         RxFateReport(byte fate, long driverTimestampUSec, byte frameType, byte[] frameBytes) {
   2594             super(fate, driverTimestampUSec, frameType, frameBytes);
   2595         }
   2596 
   2597         @Override
   2598         protected String directionToString() {
   2599             return "RX";
   2600         }
   2601 
   2602         @Override
   2603         protected String fateToString() {
   2604             switch (mFate) {
   2605                 case WifiLoggerHal.RX_PKT_FATE_SUCCESS:
   2606                     return "success";
   2607                 case WifiLoggerHal.RX_PKT_FATE_FW_QUEUED:
   2608                     return "firmware queued";
   2609                 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER:
   2610                     return "firmware dropped (filter)";
   2611                 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID:
   2612                     return "firmware dropped (invalid frame)";
   2613                 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS:
   2614                     return "firmware dropped (no bufs)";
   2615                 case WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER:
   2616                     return "firmware dropped (other)";
   2617                 case WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED:
   2618                     return "driver queued";
   2619                 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER:
   2620                     return "driver dropped (filter)";
   2621                 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID:
   2622                     return "driver dropped (invalid frame)";
   2623                 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS:
   2624                     return "driver dropped (no bufs)";
   2625                 case WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER:
   2626                     return "driver dropped (other)";
   2627                 default:
   2628                     return Byte.toString(mFate);
   2629             }
   2630         }
   2631     }
   2632 
   2633     /**
   2634      * Ask the HAL to enable packet fate monitoring. Fails unless HAL is started.
   2635      *
   2636      * @param ifaceName Name of the interface.
   2637      * @return true for success, false otherwise.
   2638      */
   2639     public boolean startPktFateMonitoring(@NonNull String ifaceName) {
   2640         return mWifiVendorHal.startPktFateMonitoring(ifaceName);
   2641     }
   2642 
   2643     /**
   2644      * Fetch the most recent TX packet fates from the HAL. Fails unless HAL is started.
   2645      *
   2646      * @param ifaceName Name of the interface.
   2647      * @return true for success, false otherwise.
   2648      */
   2649     public boolean getTxPktFates(@NonNull String ifaceName, TxFateReport[] reportBufs) {
   2650         return mWifiVendorHal.getTxPktFates(ifaceName, reportBufs);
   2651     }
   2652 
   2653     /**
   2654      * Fetch the most recent RX packet fates from the HAL. Fails unless HAL is started.
   2655      * @param ifaceName Name of the interface.
   2656      */
   2657     public boolean getRxPktFates(@NonNull String ifaceName, RxFateReport[] reportBufs) {
   2658         return mWifiVendorHal.getRxPktFates(ifaceName, reportBufs);
   2659     }
   2660 
   2661     /**
   2662      * Get the tx packet counts for the interface.
   2663      *
   2664      * @param ifaceName Name of the interface.
   2665      * @return tx packet counts
   2666      */
   2667     public long getTxPackets(@NonNull String ifaceName) {
   2668         return TrafficStats.getTxPackets(ifaceName);
   2669     }
   2670 
   2671     /**
   2672      * Get the rx packet counts for the interface.
   2673      *
   2674      * @param ifaceName Name of the interface
   2675      * @return rx packet counts
   2676      */
   2677     public long getRxPackets(@NonNull String ifaceName) {
   2678         return TrafficStats.getRxPackets(ifaceName);
   2679     }
   2680 
   2681     /**
   2682      * Start sending the specified keep alive packets periodically.
   2683      *
   2684      * @param ifaceName Name of the interface.
   2685      * @param slot Integer used to identify each request.
   2686      * @param dstMac Destination MAC Address
   2687      * @param packet Raw packet contents to send.
   2688      * @param protocol The ethernet protocol type
   2689      * @param period Period to use for sending these packets.
   2690      * @return 0 for success, -1 for error
   2691      */
   2692     public int startSendingOffloadedPacket(@NonNull String ifaceName, int slot,
   2693             byte[] dstMac, byte[] packet, int protocol, int period) {
   2694         byte[] srcMac = NativeUtil.macAddressToByteArray(getMacAddress(ifaceName));
   2695         return mWifiVendorHal.startSendingOffloadedPacket(
   2696                 ifaceName, slot, srcMac, dstMac, packet, protocol, period);
   2697     }
   2698 
   2699     /**
   2700      * Stop sending the specified keep alive packets.
   2701      *
   2702      * @param ifaceName Name of the interface.
   2703      * @param slot id - same as startSendingOffloadedPacket call.
   2704      * @return 0 for success, -1 for error
   2705      */
   2706     public int stopSendingOffloadedPacket(@NonNull String ifaceName, int slot) {
   2707         return mWifiVendorHal.stopSendingOffloadedPacket(ifaceName, slot);
   2708     }
   2709 
   2710     public static interface WifiRssiEventHandler {
   2711         void onRssiThresholdBreached(byte curRssi);
   2712     }
   2713 
   2714     /**
   2715      * Start RSSI monitoring on the currently connected access point.
   2716      *
   2717      * @param ifaceName        Name of the interface.
   2718      * @param maxRssi          Maximum RSSI threshold.
   2719      * @param minRssi          Minimum RSSI threshold.
   2720      * @param rssiEventHandler Called when RSSI goes above maxRssi or below minRssi
   2721      * @return 0 for success, -1 for failure
   2722      */
   2723     public int startRssiMonitoring(
   2724             @NonNull String ifaceName, byte maxRssi, byte minRssi,
   2725             WifiRssiEventHandler rssiEventHandler) {
   2726         return mWifiVendorHal.startRssiMonitoring(
   2727                 ifaceName, maxRssi, minRssi, rssiEventHandler);
   2728     }
   2729 
   2730     /**
   2731      * Stop RSSI monitoring on the currently connected access point.
   2732      *
   2733      * @param ifaceName Name of the interface.
   2734      * @return 0 for success, -1 for failure
   2735      */
   2736     public int stopRssiMonitoring(@NonNull String ifaceName) {
   2737         return mWifiVendorHal.stopRssiMonitoring(ifaceName);
   2738     }
   2739 
   2740     /**
   2741      * Fetch the host wakeup reasons stats from wlan driver.
   2742      *
   2743      * @return the |WifiWakeReasonAndCounts| object retrieved from the wlan driver.
   2744      */
   2745     public WifiWakeReasonAndCounts getWlanWakeReasonCount() {
   2746         return mWifiVendorHal.getWlanWakeReasonCount();
   2747     }
   2748 
   2749     /**
   2750      * Enable/Disable Neighbour discovery offload functionality in the firmware.
   2751      *
   2752      * @param ifaceName Name of the interface.
   2753      * @param enabled true to enable, false to disable.
   2754      * @return true for success, false otherwise.
   2755      */
   2756     public boolean configureNeighborDiscoveryOffload(@NonNull String ifaceName, boolean enabled) {
   2757         return mWifiVendorHal.configureNeighborDiscoveryOffload(ifaceName, enabled);
   2758     }
   2759 
   2760     // Firmware roaming control.
   2761 
   2762     /**
   2763      * Class to retrieve firmware roaming capability parameters.
   2764      */
   2765     public static class RoamingCapabilities {
   2766         public int  maxBlacklistSize;
   2767         public int  maxWhitelistSize;
   2768     }
   2769 
   2770     /**
   2771      * Query the firmware roaming capabilities.
   2772      * @param ifaceName Name of the interface.
   2773      * @return true for success, false otherwise.
   2774      */
   2775     public boolean getRoamingCapabilities(
   2776             @NonNull String ifaceName, RoamingCapabilities capabilities) {
   2777         return mWifiVendorHal.getRoamingCapabilities(ifaceName, capabilities);
   2778     }
   2779 
   2780     /**
   2781      * Macros for controlling firmware roaming.
   2782      */
   2783     public static final int DISABLE_FIRMWARE_ROAMING = 0;
   2784     public static final int ENABLE_FIRMWARE_ROAMING = 1;
   2785 
   2786     /**
   2787      * Enable/disable firmware roaming.
   2788      *
   2789      * @param ifaceName Name of the interface.
   2790      * @return error code returned from HAL.
   2791      */
   2792     public int enableFirmwareRoaming(@NonNull String ifaceName, int state) {
   2793         return mWifiVendorHal.enableFirmwareRoaming(ifaceName, state);
   2794     }
   2795 
   2796     /**
   2797      * Class for specifying the roaming configurations.
   2798      */
   2799     public static class RoamingConfig {
   2800         public ArrayList<String> blacklistBssids;
   2801         public ArrayList<String> whitelistSsids;
   2802     }
   2803 
   2804     /**
   2805      * Set firmware roaming configurations.
   2806      * @param ifaceName Name of the interface.
   2807      */
   2808     public boolean configureRoaming(@NonNull String ifaceName, RoamingConfig config) {
   2809         return mWifiVendorHal.configureRoaming(ifaceName, config);
   2810     }
   2811 
   2812     /**
   2813      * Reset firmware roaming configuration.
   2814      * @param ifaceName Name of the interface.
   2815      */
   2816     public boolean resetRoamingConfiguration(@NonNull String ifaceName) {
   2817         // Pass in an empty RoamingConfig object which translates to zero size
   2818         // blacklist and whitelist to reset the firmware roaming configuration.
   2819         return mWifiVendorHal.configureRoaming(ifaceName, new RoamingConfig());
   2820     }
   2821 
   2822     /**
   2823      * Tx power level scenarios that can be selected.
   2824      */
   2825     public static final int TX_POWER_SCENARIO_NORMAL = 0;
   2826     public static final int TX_POWER_SCENARIO_VOICE_CALL = 1;
   2827 
   2828     /**
   2829      * Select one of the pre-configured TX power level scenarios or reset it back to normal.
   2830      * Primarily used for meeting SAR requirements during voice calls.
   2831      *
   2832      * @param scenario Should be one {@link #TX_POWER_SCENARIO_NORMAL} or
   2833      *        {@link #TX_POWER_SCENARIO_VOICE_CALL}.
   2834      * @return true for success; false for failure or if the HAL version does not support this API.
   2835      */
   2836     public boolean selectTxPowerScenario(int scenario) {
   2837         return mWifiVendorHal.selectTxPowerScenario(scenario);
   2838     }
   2839 
   2840     /********************************************************
   2841      * JNI operations
   2842      ********************************************************/
   2843     /* Register native functions */
   2844     static {
   2845         /* Native functions are defined in libwifi-service.so */
   2846         System.loadLibrary("wifi-service");
   2847         registerNatives();
   2848     }
   2849 
   2850     private static native int registerNatives();
   2851     /* kernel logging support */
   2852     private static native byte[] readKernelLogNative();
   2853 
   2854     /**
   2855      * Fetches the latest kernel logs.
   2856      */
   2857     public synchronized String readKernelLog() {
   2858         byte[] bytes = readKernelLogNative();
   2859         if (bytes != null) {
   2860             CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
   2861             try {
   2862                 CharBuffer decoded = decoder.decode(ByteBuffer.wrap(bytes));
   2863                 return decoded.toString();
   2864             } catch (CharacterCodingException cce) {
   2865                 return new String(bytes, StandardCharsets.ISO_8859_1);
   2866             }
   2867         } else {
   2868             return "*** failed to read kernel log ***";
   2869         }
   2870     }
   2871 }
   2872