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