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