• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 package com.android.server.wifi;
17 
18 import static android.net.wifi.WifiManager.WIFI_FEATURE_DECORATED_IDENTITY;
19 import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP;
20 import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP_ENROLLEE_RESPONDER;
21 import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256;
22 import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384;
23 import static android.net.wifi.WifiManager.WIFI_FEATURE_MBO;
24 import static android.net.wifi.WifiManager.WIFI_FEATURE_OCE;
25 import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
26 import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS;
27 import static android.net.wifi.WifiManager.WIFI_FEATURE_SAE_PK;
28 import static android.net.wifi.WifiManager.WIFI_FEATURE_WAPI;
29 import static android.net.wifi.WifiManager.WIFI_FEATURE_WFD_R2;
30 import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
31 import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
32 
33 import android.annotation.NonNull;
34 import android.content.Context;
35 import android.hardware.wifi.V1_0.WifiChannelWidthInMhz;
36 import android.hardware.wifi.supplicant.V1_0.ISupplicant;
37 import android.hardware.wifi.supplicant.V1_0.ISupplicantIface;
38 import android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork;
39 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface;
40 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
41 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork;
42 import android.hardware.wifi.supplicant.V1_0.IfaceType;
43 import android.hardware.wifi.supplicant.V1_0.SupplicantStatus;
44 import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode;
45 import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods;
46 import android.hardware.wifi.supplicant.V1_2.DppAkm;
47 import android.hardware.wifi.supplicant.V1_2.DppNetRole;
48 import android.hardware.wifi.supplicant.V1_3.ConnectionCapabilities;
49 import android.hardware.wifi.supplicant.V1_3.WifiTechnology;
50 import android.hardware.wifi.supplicant.V1_3.WpaDriverCapabilitiesMask;
51 import android.hardware.wifi.supplicant.V1_4.DppCurve;
52 import android.hardware.wifi.supplicant.V1_4.LegacyMode;
53 import android.hidl.manager.V1_0.IServiceManager;
54 import android.hidl.manager.V1_0.IServiceNotification;
55 import android.net.MacAddress;
56 import android.net.wifi.ScanResult;
57 import android.net.wifi.SecurityParams;
58 import android.net.wifi.WifiAnnotations.WifiStandard;
59 import android.net.wifi.WifiConfiguration;
60 import android.os.Handler;
61 import android.os.IHwBinder.DeathRecipient;
62 import android.os.RemoteException;
63 import android.text.TextUtils;
64 import android.util.Log;
65 import android.util.Pair;
66 
67 import com.android.internal.annotations.VisibleForTesting;
68 import com.android.server.wifi.WifiNative.DppEventCallback;
69 import com.android.server.wifi.WifiNative.SupplicantDeathEventHandler;
70 import com.android.server.wifi.util.GeneralUtil.Mutable;
71 import com.android.server.wifi.util.NativeUtil;
72 
73 import java.nio.ByteBuffer;
74 import java.nio.ByteOrder;
75 import java.util.ArrayList;
76 import java.util.HashMap;
77 import java.util.List;
78 import java.util.Map;
79 import java.util.NoSuchElementException;
80 import java.util.Objects;
81 import java.util.Random;
82 import java.util.concurrent.CountDownLatch;
83 import java.util.concurrent.TimeUnit;
84 import java.util.regex.Matcher;
85 import java.util.regex.Pattern;
86 
87 import javax.annotation.concurrent.ThreadSafe;
88 
89 /**
90  * Hal calls for bring up/shut down of the supplicant daemon and for
91  * sending requests to the supplicant daemon
92  * To maintain thread-safety, the locking protocol is that every non-static method (regardless of
93  * access level) acquires mLock.
94  */
95 @ThreadSafe
96 public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal {
97     private static final String TAG = "SupplicantStaIfaceHalHidlImp";
98     @VisibleForTesting
99     public static final String HAL_INSTANCE_NAME = "default";
100     @VisibleForTesting
101     public static final long WAIT_FOR_DEATH_TIMEOUT_MS = 50L;
102     /**
103      * Regex pattern for extracting the wps device type bytes.
104      * Matches a strings like the following: "<categ>-<OUI>-<subcateg>";
105      */
106     private static final Pattern WPS_DEVICE_TYPE_PATTERN =
107             Pattern.compile("^(\\d{1,2})-([0-9a-fA-F]{8})-(\\d{1,2})$");
108 
109     private final Object mLock = new Object();
110     private boolean mVerboseLoggingEnabled = false;
111     private boolean mVerboseHalLoggingEnabled = false;
112 
113     // Supplicant HAL interface objects
114     private IServiceManager mIServiceManager = null;
115     private ISupplicant mISupplicant;
116     private Map<String, ISupplicantStaIface> mISupplicantStaIfaces = new HashMap<>();
117     private Map<String, ISupplicantStaIfaceCallback> mISupplicantStaIfaceCallbacks =
118             new HashMap<>();
119     private Map<String, SupplicantStaNetworkHalHidlImpl> mCurrentNetworkRemoteHandles =
120             new HashMap<>();
121     private Map<String, WifiConfiguration> mCurrentNetworkLocalConfigs = new HashMap<>();
122     private Map<String, List<Pair<SupplicantStaNetworkHalHidlImpl, WifiConfiguration>>>
123             mLinkedNetworkLocalAndRemoteConfigs = new HashMap<>();
124     @VisibleForTesting
125     PmkCacheManager mPmkCacheManager;
126     private SupplicantDeathEventHandler mDeathEventHandler;
127     private ServiceManagerDeathRecipient mServiceManagerDeathRecipient;
128     private SupplicantDeathRecipient mSupplicantDeathRecipient;
129     // Death recipient cookie registered for current supplicant instance.
130     private long mDeathRecipientCookie = 0;
131     private final Context mContext;
132     private final WifiMonitor mWifiMonitor;
133     private final FrameworkFacade mFrameworkFacade;
134     private final Handler mEventHandler;
135     private DppEventCallback mDppCallback = null;
136     private final Clock mClock;
137     private final WifiMetrics mWifiMetrics;
138     private final WifiGlobals mWifiGlobals;
139 
140     private final IServiceNotification mServiceNotificationCallback =
141             new IServiceNotification.Stub() {
142                 public void onRegistration(String fqName, String name, boolean preexisting) {
143                     synchronized (mLock) {
144                         if (mVerboseLoggingEnabled) {
145                             Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName
146                                     + ", " + name + " preexisting=" + preexisting);
147                         }
148                         if (!initSupplicantService()) {
149                             Log.e(TAG, "Initializing ISupplicant failed.");
150                             supplicantServiceDiedHandler(mDeathRecipientCookie);
151                         } else {
152                             Log.i(TAG, "Completed initialization of ISupplicant.");
153                         }
154                     }
155                 }
156             };
157     private class ServiceManagerDeathRecipient implements DeathRecipient {
158         @Override
serviceDied(long cookie)159         public void serviceDied(long cookie) {
160             mEventHandler.post(() -> {
161                 synchronized (mLock) {
162                     Log.w(TAG, "IServiceManager died: cookie=" + cookie);
163                     supplicantServiceDiedHandler(mDeathRecipientCookie);
164                     mIServiceManager = null; // Will need to register a new ServiceNotification
165                 }
166             });
167         }
168     }
169     private class SupplicantDeathRecipient implements DeathRecipient {
170         @Override
serviceDied(long cookie)171         public void serviceDied(long cookie) {
172             mEventHandler.post(() -> {
173                 synchronized (mLock) {
174                     Log.w(TAG, "ISupplicant died: cookie=" + cookie);
175                     supplicantServiceDiedHandler(cookie);
176                 }
177             });
178         }
179     }
180 
SupplicantStaIfaceHalHidlImpl(Context context, WifiMonitor monitor, FrameworkFacade frameworkFacade, Handler handler, Clock clock, WifiMetrics wifiMetrics, WifiGlobals wifiGlobals)181     public SupplicantStaIfaceHalHidlImpl(Context context, WifiMonitor monitor,
182             FrameworkFacade frameworkFacade, Handler handler,
183             Clock clock, WifiMetrics wifiMetrics,
184             WifiGlobals wifiGlobals) {
185         mContext = context;
186         mWifiMonitor = monitor;
187         mFrameworkFacade = frameworkFacade;
188         mEventHandler = handler;
189         mClock = clock;
190         mWifiMetrics = wifiMetrics;
191         mWifiGlobals = wifiGlobals;
192 
193         mServiceManagerDeathRecipient = new ServiceManagerDeathRecipient();
194         mSupplicantDeathRecipient = new SupplicantDeathRecipient();
195         mPmkCacheManager = new PmkCacheManager(mClock, mEventHandler);
196     }
197 
198     /**
199      * Enable/Disable verbose logging.
200      * @param verboseEnabled Verbose flag set in overlay XML.
201      * @param halVerboseEnabled Verbose flag set by the user.
202      */
enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled)203     public void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) {
204         synchronized (mLock) {
205             mVerboseLoggingEnabled = verboseEnabled;
206             mVerboseHalLoggingEnabled = halVerboseEnabled;
207             setLogLevel(mVerboseHalLoggingEnabled);
208         }
209     }
210 
isVerboseLoggingEnabled()211     protected boolean isVerboseLoggingEnabled() {
212         return mVerboseLoggingEnabled;
213     }
214 
linkToServiceManagerDeath()215     private boolean linkToServiceManagerDeath() {
216         synchronized (mLock) {
217             if (mIServiceManager == null) return false;
218             try {
219                 if (!mIServiceManager.linkToDeath(mServiceManagerDeathRecipient, 0)) {
220                     Log.wtf(TAG, "Error on linkToDeath on IServiceManager");
221                     supplicantServiceDiedHandler(mDeathRecipientCookie);
222                     mIServiceManager = null; // Will need to register a new ServiceNotification
223                     return false;
224                 }
225             } catch (RemoteException e) {
226                 Log.e(TAG, "IServiceManager.linkToDeath exception", e);
227                 return false;
228             }
229             return true;
230         }
231     }
232 
233     /**
234      * Registers a service notification for the ISupplicant service, which triggers initialization
235      * of the ISupplicantStaIface
236      * @return true if the service notification was successfully registered
237      */
initialize()238     public boolean initialize() {
239         synchronized (mLock) {
240             if (mVerboseLoggingEnabled) {
241                 Log.i(TAG, "Registering ISupplicant service ready callback.");
242             }
243             mISupplicant = null;
244             mISupplicantStaIfaces.clear();
245             if (mIServiceManager != null) {
246                 // Already have an IServiceManager and serviceNotification registered, don't
247                 // don't register another.
248                 return true;
249             }
250             try {
251                 mIServiceManager = getServiceManagerMockable();
252                 if (mIServiceManager == null) {
253                     Log.e(TAG, "Failed to get HIDL Service Manager");
254                     return false;
255                 }
256                 if (!linkToServiceManagerDeath()) {
257                     return false;
258                 }
259                 /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it
260                    exists */
261                 if (!mIServiceManager.registerForNotifications(
262                         ISupplicant.kInterfaceName, "", mServiceNotificationCallback)) {
263                     Log.e(TAG, "Failed to register for notifications to "
264                             + ISupplicant.kInterfaceName);
265                     mIServiceManager = null; // Will need to register a new ServiceNotification
266                     return false;
267                 }
268             } catch (RemoteException e) {
269                 Log.e(TAG, "Exception while trying to register a listener for "
270                         + "ISupplicant service: " + e);
271                 supplicantServiceDiedHandler(mDeathRecipientCookie);
272             }
273             return true;
274         }
275     }
276 
linkToSupplicantDeath( DeathRecipient deathRecipient, long cookie)277     private boolean linkToSupplicantDeath(
278             DeathRecipient deathRecipient, long cookie) {
279         synchronized (mLock) {
280             if (mISupplicant == null) return false;
281             try {
282                 if (!mISupplicant.linkToDeath(deathRecipient, cookie)) {
283                     Log.wtf(TAG, "Error on linkToDeath on ISupplicant");
284                     supplicantServiceDiedHandler(mDeathRecipientCookie);
285                     return false;
286                 }
287             } catch (RemoteException e) {
288                 Log.e(TAG, "ISupplicant.linkToDeath exception", e);
289                 return false;
290             }
291             return true;
292         }
293     }
294 
initSupplicantService()295     private boolean initSupplicantService() {
296         synchronized (mLock) {
297             try {
298                 mISupplicant = getSupplicantMockable();
299             } catch (RemoteException e) {
300                 Log.e(TAG, "ISupplicant.getService exception: " + e);
301                 return false;
302             } catch (NoSuchElementException e) {
303                 Log.e(TAG, "ISupplicant.getService exception: " + e);
304                 return false;
305             }
306             if (mISupplicant == null) {
307                 Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup");
308                 return false;
309             }
310             if (!linkToSupplicantDeath(mSupplicantDeathRecipient, ++mDeathRecipientCookie)) {
311                 return false;
312             }
313         }
314         return true;
315     }
316 
getCurrentNetworkId(@onNull String ifaceName)317     protected int getCurrentNetworkId(@NonNull String ifaceName) {
318         synchronized (mLock) {
319             WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
320             if (currentConfig == null) {
321                 return WifiConfiguration.INVALID_NETWORK_ID;
322             }
323             return currentConfig.networkId;
324         }
325     }
326 
trySetupStaIfaceV1_4(@onNull String ifaceName, @NonNull ISupplicantStaIface iface)327     private boolean trySetupStaIfaceV1_4(@NonNull String ifaceName,
328             @NonNull ISupplicantStaIface iface)  throws RemoteException {
329         if (!isV1_4()) return false;
330 
331         SupplicantStaIfaceHalCallbackV1_4 callbackV14 =
332                 new SupplicantStaIfaceHalCallbackV1_4(ifaceName);
333         if (!registerCallbackV1_4(getStaIfaceMockableV1_4(iface), callbackV14)) {
334             throw new RemoteException("Init StaIface V1_4 failed.");
335         }
336         /* keep this in a store to avoid recycling by garbage collector. */
337         mISupplicantStaIfaceCallbacks.put(ifaceName, callbackV14);
338         return true;
339     }
340 
trySetupStaIfaceV1_3(@onNull String ifaceName, @NonNull ISupplicantStaIface iface)341     private boolean trySetupStaIfaceV1_3(@NonNull String ifaceName,
342             @NonNull ISupplicantStaIface iface)  throws RemoteException {
343         if (!isV1_3()) return false;
344 
345         /* try newer version first. */
346         if (trySetupStaIfaceV1_4(ifaceName, iface)) {
347             logd("Newer HAL is found, skip V1_3 remaining init flow.");
348             return true;
349         }
350         SupplicantStaIfaceHalCallbackV1_3 callbackV13 =
351                 new SupplicantStaIfaceHalCallbackV1_3(ifaceName);
352         if (!registerCallbackV1_3(getStaIfaceMockableV1_3(iface), callbackV13)) {
353             throw new RemoteException("Init StaIface V1_3 failed.");
354         }
355         /* keep this in a store to avoid recycling by garbage collector. */
356         mISupplicantStaIfaceCallbacks.put(ifaceName, callbackV13);
357         return true;
358     }
359 
trySetupStaIfaceV1_2(@onNull String ifaceName, @NonNull ISupplicantStaIface iface)360     private boolean trySetupStaIfaceV1_2(@NonNull String ifaceName,
361             @NonNull ISupplicantStaIface iface) throws RemoteException {
362         if (!isV1_2()) return false;
363 
364         /* try newer version first. */
365         if (trySetupStaIfaceV1_3(ifaceName, iface)) {
366             logd("Newer HAL is found, skip V1_2 remaining init flow.");
367             return true;
368         }
369 
370         SupplicantStaIfaceHalCallbackV1_2 callbackV12 =
371                 new SupplicantStaIfaceHalCallbackV1_2(ifaceName);
372         if (!registerCallbackV1_2(getStaIfaceMockableV1_2(iface), callbackV12)) {
373             throw new RemoteException("Init StaIface V1_2 failed.");
374         }
375         /* keep this in a store to avoid recycling by garbage collector. */
376         mISupplicantStaIfaceCallbacks.put(ifaceName, callbackV12);
377         return true;
378     }
379 
trySetupStaIfaceV1_1(@onNull String ifaceName, @NonNull ISupplicantStaIface iface)380     private boolean trySetupStaIfaceV1_1(@NonNull String ifaceName,
381             @NonNull ISupplicantStaIface iface) throws RemoteException {
382         if (!isV1_1()) return false;
383 
384         /* try newer version first. */
385         if (trySetupStaIfaceV1_2(ifaceName, iface)) {
386             logd("Newer HAL is found, skip V1_1 remaining init flow.");
387             return true;
388         }
389 
390         SupplicantStaIfaceHalCallbackV1_1 callbackV11 =
391                 new SupplicantStaIfaceHalCallbackV1_1(ifaceName);
392         if (!registerCallbackV1_1(getStaIfaceMockableV1_1(iface), callbackV11)) {
393             throw new RemoteException("Init StaIface V1_1 failed.");
394         }
395         /* keep this in a store to avoid recycling by garbage collector. */
396         mISupplicantStaIfaceCallbacks.put(ifaceName, callbackV11);
397         return true;
398     }
399 
400     /**
401      * Helper function to set up StaIface with different HAL version.
402      *
403      * This helper function would try newer version recursively.
404      * Once the latest version is found, it would register the callback
405      * of the latest version and skip unnecessary older HAL init flow.
406      *
407      * New version callback will be extended from the older one, as a result,
408      * older callback is always created regardless of the latest version.
409      *
410      * Uprev steps:
411      * 1. add new helper function trySetupStaIfaceV1_Y.
412      * 2. call newly added function in trySetupStaIfaceV1_X (X should be Y-1).
413      */
setupStaIface(@onNull String ifaceName, @NonNull ISupplicantIface ifaceHwBinder)414     private ISupplicantStaIface setupStaIface(@NonNull String ifaceName,
415             @NonNull ISupplicantIface ifaceHwBinder) throws RemoteException {
416         /* Prepare base type for later cast. */
417         ISupplicantStaIface iface = getStaIfaceMockable(ifaceHwBinder);
418 
419         /* try newer version first. */
420         if (trySetupStaIfaceV1_1(ifaceName, iface)) {
421             logd("Newer HAL is found, skip V1_0 remaining init flow.");
422             return iface;
423         }
424 
425         SupplicantStaIfaceHalCallback callback = new SupplicantStaIfaceHalCallback(ifaceName);
426         if (!registerCallback(iface, callback)) {
427             throw new RemoteException("Init StaIface V1_0 failed.");
428         }
429         /* keep this in a store to avoid recycling by garbage collector. */
430         mISupplicantStaIfaceCallbacks.put(ifaceName, callback);
431         return iface;
432     }
433 
434     /**
435      * Setup a STA interface for the specified iface name.
436      *
437      * @param ifaceName Name of the interface.
438      * @return true on success, false otherwise.
439      */
setupIface(@onNull String ifaceName)440     public boolean setupIface(@NonNull String ifaceName) {
441         final String methodStr = "setupIface";
442         if (checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr) != null) return false;
443         ISupplicantIface ifaceHwBinder;
444 
445         if (isV1_1()) {
446             ifaceHwBinder = addIfaceV1_1(ifaceName);
447         } else {
448             ifaceHwBinder = getIfaceV1_0(ifaceName);
449         }
450         if (ifaceHwBinder == null) {
451             Log.e(TAG, "setupIface got null iface");
452             return false;
453         }
454 
455         try {
456             ISupplicantStaIface iface = setupStaIface(ifaceName, ifaceHwBinder);
457             mISupplicantStaIfaces.put(ifaceName, iface);
458         } catch (RemoteException e) {
459             loge("setup StaIface failed: " + e.toString());
460             return false;
461         }
462 
463         return true;
464     }
465 
466     /**
467      * Get a STA interface for the specified iface name.
468      *
469      * @param ifaceName Name of the interface.
470      * @return true on success, false otherwise.
471      */
getIfaceV1_0(@onNull String ifaceName)472     private ISupplicantIface getIfaceV1_0(@NonNull String ifaceName) {
473         synchronized (mLock) {
474             if (mISupplicant == null) {
475                 return null;
476             }
477 
478             /** List all supplicant Ifaces */
479             final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>();
480             try {
481                 mISupplicant.listInterfaces((SupplicantStatus status,
482                         ArrayList<ISupplicant.IfaceInfo> ifaces) -> {
483                     if (status.code != SupplicantStatusCode.SUCCESS) {
484                         Log.e(TAG, "Getting Supplicant Interfaces failed: " + status.code);
485                         return;
486                     }
487                     supplicantIfaces.addAll(ifaces);
488                 });
489             } catch (RemoteException e) {
490                 Log.e(TAG, "ISupplicant.listInterfaces exception: " + e);
491                 handleRemoteException(e, "listInterfaces");
492                 return null;
493             }
494             if (supplicantIfaces.size() == 0) {
495                 Log.e(TAG, "Got zero HIDL supplicant ifaces. Stopping supplicant HIDL startup.");
496                 return null;
497             }
498             Mutable<ISupplicantIface> supplicantIface = new Mutable<>();
499             for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) {
500                 if (ifaceInfo.type == IfaceType.STA
501                         && TextUtils.equals(ifaceName, ifaceInfo.name)) {
502                     try {
503                         mISupplicant.getInterface(ifaceInfo,
504                                 (SupplicantStatus status, ISupplicantIface iface) -> {
505                                     if (status.code != SupplicantStatusCode.SUCCESS) {
506                                         Log.e(TAG, "Fail to get ISupplicantIface " + status.code);
507                                         return;
508                                     }
509                                     supplicantIface.value = iface;
510                                 });
511                     } catch (RemoteException e) {
512                         Log.e(TAG, "ISupplicant.getInterface exception: " + e);
513                         handleRemoteException(e, "getInterface");
514                         return null;
515                     }
516                     break;
517                 }
518             }
519             return supplicantIface.value;
520         }
521     }
522 
523     /**
524      * Create a STA interface for the specified iface name.
525      *
526      * @param ifaceName Name of the interface.
527      * @return true on success, false otherwise.
528      */
addIfaceV1_1(@onNull String ifaceName)529     private ISupplicantIface addIfaceV1_1(@NonNull String ifaceName) {
530         synchronized (mLock) {
531             ISupplicant.IfaceInfo ifaceInfo = new ISupplicant.IfaceInfo();
532             ifaceInfo.name = ifaceName;
533             ifaceInfo.type = IfaceType.STA;
534             Mutable<ISupplicantIface> supplicantIface = new Mutable<>();
535             try {
536                 getSupplicantMockableV1_1().addInterface(ifaceInfo,
537                         (SupplicantStatus status, ISupplicantIface iface) -> {
538                             if (status.code != SupplicantStatusCode.SUCCESS
539                                     && status.code != SupplicantStatusCode.FAILURE_IFACE_EXISTS) {
540                                 Log.e(TAG, "Failed to create ISupplicantIface " + status.code);
541                                 return;
542                             }
543                             supplicantIface.value = iface;
544                         });
545             } catch (RemoteException e) {
546                 Log.e(TAG, "ISupplicant.addInterface exception: " + e);
547                 handleRemoteException(e, "addInterface");
548                 return null;
549             } catch (NoSuchElementException e) {
550                 Log.e(TAG, "ISupplicant.addInterface exception: " + e);
551                 handleNoSuchElementException(e, "addInterface");
552                 return null;
553             } catch (IllegalArgumentException e) {
554                 handleIllegalArgumentException(e, "addInterface");
555                 Log.e(TAG, "ISupplicant.addInterface exception: " + e);
556                 return null;
557             }
558             return supplicantIface.value;
559         }
560     }
561 
562     /**
563      * Teardown a STA interface for the specified iface name.
564      *
565      * @param ifaceName Name of the interface.
566      * @return true on success, false otherwise.
567      */
teardownIface(@onNull String ifaceName)568     public boolean teardownIface(@NonNull String ifaceName) {
569         synchronized (mLock) {
570             final String methodStr = "teardownIface";
571             if (checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr) == null) return false;
572             if (isV1_1()) {
573                 if (!removeIfaceV1_1(ifaceName)) {
574                     Log.e(TAG, "Failed to remove iface = " + ifaceName);
575                     return false;
576                 }
577             }
578             if (mISupplicantStaIfaces.remove(ifaceName) == null) {
579                 Log.e(TAG, "Trying to teardown unknown interface");
580                 return false;
581             }
582             mISupplicantStaIfaceCallbacks.remove(ifaceName);
583             return true;
584         }
585     }
586 
587     /**
588      * Remove a STA interface for the specified iface name.
589      *
590      * @param ifaceName Name of the interface.
591      * @return true on success, false otherwise.
592      */
removeIfaceV1_1(@onNull String ifaceName)593     private boolean removeIfaceV1_1(@NonNull String ifaceName) {
594         synchronized (mLock) {
595             try {
596                 ISupplicant.IfaceInfo ifaceInfo = new ISupplicant.IfaceInfo();
597                 ifaceInfo.name = ifaceName;
598                 ifaceInfo.type = IfaceType.STA;
599                 SupplicantStatus status = getSupplicantMockableV1_1().removeInterface(ifaceInfo);
600                 if (status.code != SupplicantStatusCode.SUCCESS) {
601                     Log.e(TAG, "Failed to remove iface " + status.code);
602                     return false;
603                 }
604             } catch (RemoteException e) {
605                 Log.e(TAG, "ISupplicant.removeInterface exception: " + e);
606                 handleRemoteException(e, "removeInterface");
607                 return false;
608             } catch (NoSuchElementException e) {
609                 Log.e(TAG, "ISupplicant.removeInterface exception: " + e);
610                 handleNoSuchElementException(e, "removeInterface");
611                 return false;
612             }
613             return true;
614         }
615     }
616 
617     /**
618      * Registers a death notification for supplicant.
619      * @return Returns true on success.
620      */
registerDeathHandler(@onNull SupplicantDeathEventHandler handler)621     public boolean registerDeathHandler(@NonNull SupplicantDeathEventHandler handler) {
622         if (mDeathEventHandler != null) {
623             Log.e(TAG, "Death handler already present");
624         }
625         mDeathEventHandler = handler;
626         return true;
627     }
628 
629     /**
630      * Deregisters a death notification for supplicant.
631      * @return Returns true on success.
632      */
deregisterDeathHandler()633     public boolean deregisterDeathHandler() {
634         if (mDeathEventHandler == null) {
635             Log.e(TAG, "No Death handler present");
636         }
637         mDeathEventHandler = null;
638         return true;
639     }
640 
641 
clearState()642     private void clearState() {
643         synchronized (mLock) {
644             mISupplicant = null;
645             mISupplicantStaIfaces.clear();
646             mCurrentNetworkLocalConfigs.clear();
647             mCurrentNetworkRemoteHandles.clear();
648             mLinkedNetworkLocalAndRemoteConfigs.clear();
649         }
650     }
651 
supplicantServiceDiedHandler(long cookie)652     private void supplicantServiceDiedHandler(long cookie) {
653         synchronized (mLock) {
654             if (mDeathRecipientCookie != cookie) {
655                 Log.i(TAG, "Ignoring stale death recipient notification");
656                 return;
657             }
658             clearState();
659             if (mDeathEventHandler != null) {
660                 mDeathEventHandler.onDeath();
661             }
662         }
663     }
664 
665     /**
666      * Signals whether Initialization completed successfully.
667      */
isInitializationStarted()668     public boolean isInitializationStarted() {
669         synchronized (mLock) {
670             return mIServiceManager != null;
671         }
672     }
673 
674     /**
675      * Signals whether Initialization completed successfully.
676      */
isInitializationComplete()677     public boolean isInitializationComplete() {
678         synchronized (mLock) {
679             return mISupplicant != null;
680         }
681     }
682 
683 
684     /**
685      * Start the supplicant daemon for V1_1 service.
686      *
687      * @return true on success, false otherwise.
688      */
startDaemon_V1_1()689     private boolean startDaemon_V1_1() {
690         synchronized (mLock) {
691             try {
692                 // This should startup supplicant daemon using the lazy start HAL mechanism.
693                 getSupplicantMockableV1_1();
694             } catch (RemoteException e) {
695                 Log.e(TAG, "Exception while trying to start supplicant: "
696                         + e);
697                 supplicantServiceDiedHandler(mDeathRecipientCookie);
698                 return false;
699             } catch (NoSuchElementException e) {
700                 // We're starting the daemon, so expect |NoSuchElementException|.
701                 Log.d(TAG, "Successfully triggered start of supplicant using HIDL");
702             }
703             return true;
704         }
705     }
706 
707     /**
708      * Start the supplicant daemon.
709      *
710      * @return true on success, false otherwise.
711      */
startDaemon()712     public boolean startDaemon() {
713         synchronized (mLock) {
714             if (isV1_1()) {
715                 Log.i(TAG, "Starting supplicant using HIDL");
716                 return startDaemon_V1_1();
717             } else {
718                 Log.i(TAG, "Starting supplicant using init");
719                 return mFrameworkFacade.startSupplicant();
720             }
721         }
722     }
723 
724     /**
725      * Terminate the supplicant daemon for V1_1 service.
726      */
terminate_V1_1()727     private void terminate_V1_1() {
728         synchronized (mLock) {
729             final String methodStr = "terminate";
730             if (!checkSupplicantAndLogFailure(methodStr)) return;
731             try {
732                 getSupplicantMockableV1_1().terminate();
733             } catch (RemoteException e) {
734                 handleRemoteException(e, methodStr);
735             } catch (NoSuchElementException e) {
736                 handleNoSuchElementException(e, methodStr);
737             }
738         }
739     }
740 
741     /**
742      * Terminate the supplicant daemon & wait for it's death.
743      */
terminate()744     public void terminate() {
745         synchronized (mLock) {
746             // Register for a new death listener to block until supplicant is dead.
747             final long waitForDeathCookie = new Random().nextLong();
748             final CountDownLatch waitForDeathLatch = new CountDownLatch(1);
749             linkToSupplicantDeath((cookie) -> {
750                 mEventHandler.post(() -> {
751                     Log.d(TAG, "ISupplicant died: cookie=" + cookie);
752                     if (cookie != waitForDeathCookie) return;
753                     supplicantServiceDiedHandler(mDeathRecipientCookie);
754                     waitForDeathLatch.countDown();
755                 });
756             }, waitForDeathCookie);
757 
758             if (isV1_1()) {
759                 Log.i(TAG, "Terminating supplicant using HIDL");
760                 terminate_V1_1();
761             } else {
762                 Log.i(TAG, "Terminating supplicant using init");
763                 mFrameworkFacade.stopSupplicant();
764             }
765 
766             // Now wait for death listener callback to confirm that it's dead.
767             try {
768                 if (!waitForDeathLatch.await(WAIT_FOR_DEATH_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
769                     Log.w(TAG, "Timed out waiting for confirmation of supplicant death");
770                 }
771             } catch (InterruptedException e) {
772                 Log.w(TAG, "Failed to wait for supplicant death");
773             }
774         }
775     }
776 
777     /**
778      * Indicates whether the HIDL service is declared. Uses the IServiceManager to check
779      * if the device is running a version >= V1_0 of the HAL from the VINTF for the device.
780      */
serviceDeclared()781     public static boolean serviceDeclared() {
782         try {
783             IServiceManager serviceManager = IServiceManager.getService();
784             String interfaceName = android.hardware.wifi.supplicant.V1_0.ISupplicant.kInterfaceName;
785             if (serviceManager.getTransport(interfaceName, HAL_INSTANCE_NAME)
786                     != IServiceManager.Transport.EMPTY) {
787                 return true;
788             }
789             return false;
790         } catch (RemoteException e) {
791             Log.e(TAG, "Unable to check for existence of HIDL service.");
792             return false;
793         }
794     }
795 
796     /**
797      * Wrapper functions to access static HAL methods, created to be mockable in unit tests
798      */
getServiceManagerMockable()799     protected IServiceManager getServiceManagerMockable() throws RemoteException {
800         synchronized (mLock) {
801             return IServiceManager.getService();
802         }
803     }
804 
getSupplicantMockable()805     protected ISupplicant getSupplicantMockable() throws RemoteException, NoSuchElementException {
806         synchronized (mLock) {
807             ISupplicant iSupplicant = ISupplicant.getService();
808             if (iSupplicant == null) {
809                 throw new NoSuchElementException("Cannot get root service.");
810             }
811             return iSupplicant;
812         }
813     }
814 
getSupplicantMockableV1_1()815     protected android.hardware.wifi.supplicant.V1_1.ISupplicant getSupplicantMockableV1_1()
816             throws RemoteException, NoSuchElementException {
817         synchronized (mLock) {
818             android.hardware.wifi.supplicant.V1_1.ISupplicant iSupplicantDerived =
819                     android.hardware.wifi.supplicant.V1_1.ISupplicant.castFrom(
820                             getSupplicantMockable());
821             if (iSupplicantDerived == null) {
822                 throw new NoSuchElementException("Cannot cast to V1.1 service.");
823             }
824             return iSupplicantDerived;
825         }
826     }
827 
getSupplicantMockableV1_2()828     protected android.hardware.wifi.supplicant.V1_2.ISupplicant getSupplicantMockableV1_2()
829             throws RemoteException, NoSuchElementException {
830         synchronized (mLock) {
831             android.hardware.wifi.supplicant.V1_2.ISupplicant iSupplicantDerived =
832                     android.hardware.wifi.supplicant.V1_2.ISupplicant.castFrom(
833                             getSupplicantMockable());
834             if (iSupplicantDerived == null) {
835                 throw new NoSuchElementException("Cannot cast to V1.1 service.");
836             }
837             return iSupplicantDerived;
838         }
839     }
840 
getStaIfaceMockable(ISupplicantIface iface)841     protected ISupplicantStaIface getStaIfaceMockable(ISupplicantIface iface) {
842         synchronized (mLock) {
843             return ISupplicantStaIface.asInterface(iface.asBinder());
844         }
845     }
846 
847     protected android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface
getStaIfaceMockableV1_1(ISupplicantIface iface)848             getStaIfaceMockableV1_1(ISupplicantIface iface) {
849         synchronized (mLock) {
850             return android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface
851                     .asInterface(iface.asBinder());
852         }
853     }
854 
855     protected android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface
getStaIfaceMockableV1_2(ISupplicantIface iface)856             getStaIfaceMockableV1_2(ISupplicantIface iface) {
857         synchronized (mLock) {
858             return android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface
859                     .asInterface(iface.asBinder());
860         }
861     }
862 
863     protected android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface
getStaIfaceMockableV1_3(ISupplicantIface iface)864             getStaIfaceMockableV1_3(ISupplicantIface iface) {
865         synchronized (mLock) {
866             return android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface
867                     .asInterface(iface.asBinder());
868         }
869     }
870 
871     protected android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface
getStaIfaceMockableV1_4(ISupplicantIface iface)872             getStaIfaceMockableV1_4(ISupplicantIface iface) {
873         synchronized (mLock) {
874             return android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface
875                     .asInterface(iface.asBinder());
876         }
877     }
878 
879     /**
880      * Uses the IServiceManager to check if the device is running V1_1 of the HAL from the VINTF for
881      * the device.
882      * @return true if supported, false otherwise.
883      */
isV1_1()884     private boolean isV1_1() {
885         return checkHalVersionByInterfaceName(
886                 android.hardware.wifi.supplicant.V1_1.ISupplicant.kInterfaceName);
887     }
888 
889     /**
890      * Uses the IServiceManager to check if the device is running V1_2 of the HAL from the VINTF for
891      * the device.
892      * @return true if supported, false otherwise.
893      */
isV1_2()894     private boolean isV1_2() {
895         return checkHalVersionByInterfaceName(
896                 android.hardware.wifi.supplicant.V1_2.ISupplicant.kInterfaceName);
897     }
898 
899     /**
900      * Uses the IServiceManager to check if the device is running V1_3 of the HAL from the VINTF for
901      * the device.
902      * @return true if supported, false otherwise.
903      */
isV1_3()904     private boolean isV1_3() {
905         return checkHalVersionByInterfaceName(
906                 android.hardware.wifi.supplicant.V1_3.ISupplicant.kInterfaceName);
907     }
908 
909     /**
910      * Uses the IServiceManager to check if the device is running V1_4 of the HAL from the VINTF for
911      * the device.
912      * @return true if supported, false otherwise.
913      */
isV1_4()914     private boolean isV1_4() {
915         return checkHalVersionByInterfaceName(
916                 android.hardware.wifi.supplicant.V1_4.ISupplicant.kInterfaceName);
917     }
918 
checkHalVersionByInterfaceName(String interfaceName)919     private boolean checkHalVersionByInterfaceName(String interfaceName) {
920         if (interfaceName == null) {
921             return false;
922         }
923         synchronized (mLock) {
924             if (mIServiceManager == null) {
925                 Log.e(TAG, "checkHalVersionByInterfaceName: called but "
926                         + "mServiceManager is null");
927                 return false;
928             }
929             try {
930                 return (mIServiceManager.getTransport(
931                         interfaceName,
932                         HAL_INSTANCE_NAME)
933                         != IServiceManager.Transport.EMPTY);
934             } catch (RemoteException e) {
935                 Log.e(TAG, "Exception while operating on IServiceManager: " + e);
936                 handleRemoteException(e, "getTransport");
937                 return false;
938             }
939         }
940     }
941 
942     /**
943      * Helper method to look up the network object for the specified iface.
944      */
getStaIface(@onNull String ifaceName)945     private ISupplicantStaIface getStaIface(@NonNull String ifaceName) {
946         return mISupplicantStaIfaces.get(ifaceName);
947     }
948 
949     /**
950      * Helper method to look up the network object for the specified iface.
951      */
getCurrentNetworkRemoteHandle( @onNull String ifaceName)952     private SupplicantStaNetworkHalHidlImpl getCurrentNetworkRemoteHandle(
953             @NonNull String ifaceName) {
954         return mCurrentNetworkRemoteHandles.get(ifaceName);
955     }
956 
957     /**
958      * Helper method to look up the network config for the specified iface.
959      */
getCurrentNetworkLocalConfig(@onNull String ifaceName)960     protected WifiConfiguration getCurrentNetworkLocalConfig(@NonNull String ifaceName) {
961         return mCurrentNetworkLocalConfigs.get(ifaceName);
962     }
963 
964     /**
965      * Add a network configuration to wpa_supplicant.
966      *
967      * @param config Config corresponding to the network.
968      * @return a Pair object including SupplicantStaNetworkHal and WifiConfiguration objects
969      * for the current network.
970      */
971     private Pair<SupplicantStaNetworkHalHidlImpl, WifiConfiguration>
addNetworkAndSaveConfig(@onNull String ifaceName, WifiConfiguration config)972             addNetworkAndSaveConfig(@NonNull String ifaceName, WifiConfiguration config) {
973         synchronized (mLock) {
974             logi("addSupplicantStaNetwork via HIDL");
975             if (config == null) {
976                 loge("Cannot add NULL network!");
977                 return null;
978             }
979             SupplicantStaNetworkHalHidlImpl network = addNetwork(ifaceName);
980             if (network == null) {
981                 loge("Failed to add a network!");
982                 return null;
983             }
984             boolean saveSuccess = false;
985             try {
986                 saveSuccess = network.saveWifiConfiguration(config);
987             } catch (IllegalArgumentException e) {
988                 Log.e(TAG, "Exception while saving config params: " + config, e);
989             }
990             if (!saveSuccess) {
991                 loge("Failed to save variables for: " + config.getProfileKey());
992                 if (!removeAllNetworks(ifaceName)) {
993                     loge("Failed to remove all networks on failure.");
994                 }
995                 return null;
996             }
997             return new Pair(network, new WifiConfiguration(config));
998         }
999     }
1000 
1001     /**
1002      * Add the provided network configuration to wpa_supplicant and initiate connection to it.
1003      * This method does the following:
1004      * 1. If |config| is different to the current supplicant network, removes all supplicant
1005      * networks and saves |config|.
1006      * 2. Select the new network in wpa_supplicant.
1007      *
1008      * @param ifaceName Name of the interface.
1009      * @param config WifiConfiguration parameters for the provided network.
1010      * @return {@code true} if it succeeds, {@code false} otherwise
1011      */
connectToNetwork(@onNull String ifaceName, @NonNull WifiConfiguration config)1012     public boolean connectToNetwork(@NonNull String ifaceName, @NonNull WifiConfiguration config) {
1013         synchronized (mLock) {
1014             logd("connectToNetwork " + config.getProfileKey());
1015             WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
1016             if (WifiConfigurationUtil.isSameNetwork(config, currentConfig)) {
1017                 String networkSelectionBSSID = config.getNetworkSelectionStatus()
1018                         .getNetworkSelectionBSSID();
1019                 String networkSelectionBSSIDCurrent =
1020                         currentConfig.getNetworkSelectionStatus().getNetworkSelectionBSSID();
1021                 if (Objects.equals(networkSelectionBSSID, networkSelectionBSSIDCurrent)) {
1022                     logd("Network is already saved, will not trigger remove and add operation.");
1023                 } else {
1024                     logd("Network is already saved, but need to update BSSID.");
1025                     if (!setCurrentNetworkBssid(
1026                             ifaceName,
1027                             config.getNetworkSelectionStatus().getNetworkSelectionBSSID())) {
1028                         loge("Failed to set current network BSSID.");
1029                         return false;
1030                     }
1031                     mCurrentNetworkLocalConfigs.put(ifaceName, new WifiConfiguration(config));
1032                 }
1033             } else {
1034                 mCurrentNetworkRemoteHandles.remove(ifaceName);
1035                 mCurrentNetworkLocalConfigs.remove(ifaceName);
1036                 mLinkedNetworkLocalAndRemoteConfigs.remove(ifaceName);
1037                 if (!removeAllNetworks(ifaceName)) {
1038                     loge("Failed to remove existing networks");
1039                     return false;
1040                 }
1041                 Pair<SupplicantStaNetworkHalHidlImpl, WifiConfiguration> pair =
1042                         addNetworkAndSaveConfig(ifaceName, config);
1043                 if (pair == null) {
1044                     loge("Failed to add/save network configuration: " + config
1045                             .getProfileKey());
1046                     return false;
1047                 }
1048                 mCurrentNetworkRemoteHandles.put(ifaceName, pair.first);
1049                 mCurrentNetworkLocalConfigs.put(ifaceName, pair.second);
1050             }
1051             SupplicantStaNetworkHalHidlImpl networkHandle =
1052                     checkSupplicantStaNetworkAndLogFailure(ifaceName, "connectToNetwork");
1053             if (networkHandle == null) {
1054                 loge("No valid remote network handle for network configuration: "
1055                         + config.getProfileKey());
1056                 return false;
1057             }
1058 
1059             SecurityParams params = config.getNetworkSelectionStatus()
1060                     .getCandidateSecurityParams();
1061             if (params != null && !params.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK)) {
1062                 List<ArrayList<Byte>> pmkDataList = mPmkCacheManager.get(config.networkId);
1063                 if (pmkDataList != null) {
1064                     logi("Set PMK cache for config id " + config.networkId);
1065                     pmkDataList.forEach(pmkData -> {
1066                         if (networkHandle.setPmkCache(pmkData)) {
1067                             mWifiMetrics.setConnectionPmkCache(ifaceName, true);
1068                         }
1069                     });
1070                 }
1071             }
1072 
1073             if (!networkHandle.select()) {
1074                 loge("Failed to select network configuration: " + config.getProfileKey());
1075                 return false;
1076             }
1077             return true;
1078         }
1079     }
1080 
1081     /**
1082      * Initiates roaming to the already configured network in wpa_supplicant. If the network
1083      * configuration provided does not match the already configured network, then this triggers
1084      * a new connection attempt (instead of roam).
1085      * 1. First check if we're attempting to connect to a linked network, and select the existing
1086      *    supplicant network if there is one.
1087      * 2. Set the new bssid for the network in wpa_supplicant.
1088      * 3. Trigger reassociate command to wpa_supplicant.
1089      *
1090      * @param ifaceName Name of the interface.
1091      * @param config WifiConfiguration parameters for the provided network.
1092      * @return {@code true} if it succeeds, {@code false} otherwise
1093      */
roamToNetwork(@onNull String ifaceName, WifiConfiguration config)1094     public boolean roamToNetwork(@NonNull String ifaceName, WifiConfiguration config) {
1095         synchronized (mLock) {
1096             if (updateOnLinkedNetworkRoaming(ifaceName, config.networkId, true)) {
1097                 SupplicantStaNetworkHalHidlImpl networkHandle =
1098                         getCurrentNetworkRemoteHandle(ifaceName);
1099                 if (networkHandle == null) {
1100                     loge("Roaming config matches a linked config, but a linked network handle was"
1101                             + " not found.");
1102                     return false;
1103                 }
1104                 return networkHandle.select();
1105             }
1106             if (getCurrentNetworkId(ifaceName) != config.networkId) {
1107                 Log.w(TAG, "Cannot roam to a different network, initiate new connection. "
1108                         + "Current network ID: " + getCurrentNetworkId(ifaceName));
1109                 return connectToNetwork(ifaceName, config);
1110             }
1111             String bssid = config.getNetworkSelectionStatus().getNetworkSelectionBSSID();
1112             logd("roamToNetwork" + config.getProfileKey() + " (bssid " + bssid + ")");
1113 
1114             SupplicantStaNetworkHalHidlImpl networkHandle =
1115                     checkSupplicantStaNetworkAndLogFailure(ifaceName, "roamToNetwork");
1116             if (networkHandle == null || !networkHandle.setBssid(bssid)) {
1117                 loge("Failed to set new bssid on network: " + config.getProfileKey());
1118                 return false;
1119             }
1120             if (!reassociate(ifaceName)) {
1121                 loge("Failed to trigger reassociate");
1122                 return false;
1123             }
1124             return true;
1125         }
1126     }
1127 
1128     /**
1129      * Clean HAL cached data for |networkId| in the framework.
1130      *
1131      * @param networkId network id of the network to be removed from supplicant.
1132      */
removeNetworkCachedData(int networkId)1133     public void removeNetworkCachedData(int networkId) {
1134         synchronized (mLock) {
1135             logd("Remove cached HAL data for config id " + networkId);
1136             removePmkCacheEntry(networkId);
1137         }
1138     }
1139 
1140     /**
1141      * Clear HAL cached data if MAC address is changed.
1142      *
1143      * @param networkId network id of the network to be checked.
1144      * @param curMacAddress current MAC address
1145      */
removeNetworkCachedDataIfNeeded(int networkId, MacAddress curMacAddress)1146     public void removeNetworkCachedDataIfNeeded(int networkId, MacAddress curMacAddress) {
1147         synchronized (mLock) {
1148             mPmkCacheManager.remove(networkId, curMacAddress);
1149         }
1150     }
1151 
1152     /**
1153      * Remove all networks from supplicant
1154      *
1155      * @param ifaceName Name of the interface.
1156      */
removeAllNetworks(@onNull String ifaceName)1157     public boolean removeAllNetworks(@NonNull String ifaceName) {
1158         synchronized (mLock) {
1159             ArrayList<Integer> networks = listNetworks(ifaceName);
1160             if (networks == null) {
1161                 Log.e(TAG, "removeAllNetworks failed, got null networks");
1162                 return false;
1163             }
1164             for (int id : networks) {
1165                 if (!removeNetwork(ifaceName, id)) {
1166                     Log.e(TAG, "removeAllNetworks failed to remove network: " + id);
1167                     return false;
1168                 }
1169             }
1170             // Reset current network info.
1171             mCurrentNetworkRemoteHandles.remove(ifaceName);
1172             mCurrentNetworkLocalConfigs.remove(ifaceName);
1173             mLinkedNetworkLocalAndRemoteConfigs.remove(ifaceName);
1174             return true;
1175         }
1176     }
1177 
1178     /**
1179      * Disable the current network in supplicant
1180      *
1181      * @param ifaceName Name of the interface.
1182      */
disableCurrentNetwork(@onNull String ifaceName)1183     public boolean disableCurrentNetwork(@NonNull String ifaceName) {
1184         synchronized (mLock) {
1185             SupplicantStaNetworkHalHidlImpl networkHandle =
1186                     checkSupplicantStaNetworkAndLogFailure(ifaceName, "disableCurrentNetwork");
1187             if (networkHandle == null) return false;
1188             return networkHandle.disable();
1189         }
1190     }
1191 
1192     /**
1193      * Set the currently configured network's bssid.
1194      *
1195      * @param ifaceName Name of the interface.
1196      * @param bssidStr Bssid to set in the form of "XX:XX:XX:XX:XX:XX"
1197      * @return true if succeeds, false otherwise.
1198      */
setCurrentNetworkBssid(@onNull String ifaceName, String bssidStr)1199     public boolean setCurrentNetworkBssid(@NonNull String ifaceName, String bssidStr) {
1200         synchronized (mLock) {
1201             SupplicantStaNetworkHalHidlImpl networkHandle =
1202                     checkSupplicantStaNetworkAndLogFailure(ifaceName, "setCurrentNetworkBssid");
1203             if (networkHandle == null) return false;
1204             return networkHandle.setBssid(bssidStr);
1205         }
1206     }
1207 
1208     /**
1209      * Get the currently configured network's WPS NFC token.
1210      *
1211      * @param ifaceName Name of the interface.
1212      * @return Hex string corresponding to the WPS NFC token.
1213      */
getCurrentNetworkWpsNfcConfigurationToken(@onNull String ifaceName)1214     public String getCurrentNetworkWpsNfcConfigurationToken(@NonNull String ifaceName) {
1215         synchronized (mLock) {
1216             SupplicantStaNetworkHalHidlImpl networkHandle =
1217                     checkSupplicantStaNetworkAndLogFailure(
1218                             ifaceName, "getCurrentNetworkWpsNfcConfigurationToken");
1219             if (networkHandle == null) return null;
1220             return networkHandle.getWpsNfcConfigurationToken();
1221         }
1222     }
1223 
1224     /**
1225      * Get the eap anonymous identity for the currently configured network.
1226      *
1227      * @param ifaceName Name of the interface.
1228      * @return anonymous identity string if succeeds, null otherwise.
1229      */
getCurrentNetworkEapAnonymousIdentity(@onNull String ifaceName)1230     public String getCurrentNetworkEapAnonymousIdentity(@NonNull String ifaceName) {
1231         synchronized (mLock) {
1232             SupplicantStaNetworkHalHidlImpl networkHandle =
1233                     checkSupplicantStaNetworkAndLogFailure(
1234                             ifaceName, "getCurrentNetworkEapAnonymousIdentity");
1235             if (networkHandle == null) return null;
1236             return networkHandle.fetchEapAnonymousIdentity();
1237         }
1238     }
1239 
1240     /**
1241      * Send the eap identity response for the currently configured network.
1242      *
1243      * @param ifaceName Name of the interface.
1244      * @param identity identity used for EAP-Identity
1245      * @param encryptedIdentity encrypted identity used for EAP-AKA/EAP-SIM
1246      * @return true if succeeds, false otherwise.
1247      */
sendCurrentNetworkEapIdentityResponse( @onNull String ifaceName, @NonNull String identity, String encryptedIdentity)1248     public boolean sendCurrentNetworkEapIdentityResponse(
1249             @NonNull String ifaceName, @NonNull String identity, String encryptedIdentity) {
1250         synchronized (mLock) {
1251             SupplicantStaNetworkHalHidlImpl networkHandle =
1252                     checkSupplicantStaNetworkAndLogFailure(
1253                             ifaceName, "sendCurrentNetworkEapIdentityResponse");
1254             if (networkHandle == null) return false;
1255             return networkHandle.sendNetworkEapIdentityResponse(identity, encryptedIdentity);
1256         }
1257     }
1258 
1259     /**
1260      * Send the eap sim gsm auth response for the currently configured network.
1261      *
1262      * @param ifaceName Name of the interface.
1263      * @param paramsStr String to send.
1264      * @return true if succeeds, false otherwise.
1265      */
sendCurrentNetworkEapSimGsmAuthResponse( @onNull String ifaceName, String paramsStr)1266     public boolean sendCurrentNetworkEapSimGsmAuthResponse(
1267             @NonNull String ifaceName, String paramsStr) {
1268         synchronized (mLock) {
1269             SupplicantStaNetworkHalHidlImpl networkHandle =
1270                     checkSupplicantStaNetworkAndLogFailure(
1271                             ifaceName, "sendCurrentNetworkEapSimGsmAuthResponse");
1272             if (networkHandle == null) return false;
1273             return networkHandle.sendNetworkEapSimGsmAuthResponse(paramsStr);
1274         }
1275     }
1276 
1277     /**
1278      * Send the eap sim gsm auth failure for the currently configured network.
1279      *
1280      * @param ifaceName Name of the interface.
1281      * @return true if succeeds, false otherwise.
1282      */
sendCurrentNetworkEapSimGsmAuthFailure(@onNull String ifaceName)1283     public boolean sendCurrentNetworkEapSimGsmAuthFailure(@NonNull String ifaceName) {
1284         synchronized (mLock) {
1285             SupplicantStaNetworkHalHidlImpl networkHandle =
1286                     checkSupplicantStaNetworkAndLogFailure(
1287                             ifaceName, "sendCurrentNetworkEapSimGsmAuthFailure");
1288             if (networkHandle == null) return false;
1289             return networkHandle.sendNetworkEapSimGsmAuthFailure();
1290         }
1291     }
1292 
1293     /**
1294      * Send the eap sim umts auth response for the currently configured network.
1295      *
1296      * @param ifaceName Name of the interface.
1297      * @param paramsStr String to send.
1298      * @return true if succeeds, false otherwise.
1299      */
sendCurrentNetworkEapSimUmtsAuthResponse( @onNull String ifaceName, String paramsStr)1300     public boolean sendCurrentNetworkEapSimUmtsAuthResponse(
1301             @NonNull String ifaceName, String paramsStr) {
1302         synchronized (mLock) {
1303             SupplicantStaNetworkHalHidlImpl networkHandle =
1304                     checkSupplicantStaNetworkAndLogFailure(
1305                             ifaceName, "sendCurrentNetworkEapSimUmtsAuthResponse");
1306             if (networkHandle == null) return false;
1307             return networkHandle.sendNetworkEapSimUmtsAuthResponse(paramsStr);
1308         }
1309     }
1310 
1311     /**
1312      * Send the eap sim umts auts response for the currently configured network.
1313      *
1314      * @param ifaceName Name of the interface.
1315      * @param paramsStr String to send.
1316      * @return true if succeeds, false otherwise.
1317      */
sendCurrentNetworkEapSimUmtsAutsResponse( @onNull String ifaceName, String paramsStr)1318     public boolean sendCurrentNetworkEapSimUmtsAutsResponse(
1319             @NonNull String ifaceName, String paramsStr) {
1320         synchronized (mLock) {
1321             SupplicantStaNetworkHalHidlImpl networkHandle =
1322                     checkSupplicantStaNetworkAndLogFailure(
1323                             ifaceName, "sendCurrentNetworkEapSimUmtsAutsResponse");
1324             if (networkHandle == null) return false;
1325             return networkHandle.sendNetworkEapSimUmtsAutsResponse(paramsStr);
1326         }
1327     }
1328 
1329     /**
1330      * Send the eap sim umts auth failure for the currently configured network.
1331      *
1332      * @param ifaceName Name of the interface.
1333      * @return true if succeeds, false otherwise.
1334      */
sendCurrentNetworkEapSimUmtsAuthFailure(@onNull String ifaceName)1335     public boolean sendCurrentNetworkEapSimUmtsAuthFailure(@NonNull String ifaceName) {
1336         synchronized (mLock) {
1337             SupplicantStaNetworkHalHidlImpl networkHandle =
1338                     checkSupplicantStaNetworkAndLogFailure(
1339                             ifaceName, "sendCurrentNetworkEapSimUmtsAuthFailure");
1340             if (networkHandle == null) return false;
1341             return networkHandle.sendNetworkEapSimUmtsAuthFailure();
1342         }
1343     }
1344 
1345     /**
1346      * Adds a new network.
1347      *
1348      * @return The ISupplicantNetwork object for the new network, or null if the call fails
1349      */
addNetwork(@onNull String ifaceName)1350     private SupplicantStaNetworkHalHidlImpl addNetwork(@NonNull String ifaceName) {
1351         synchronized (mLock) {
1352             final String methodStr = "addNetwork";
1353             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1354             if (iface == null) return null;
1355             Mutable<ISupplicantNetwork> newNetwork = new Mutable<>();
1356             try {
1357                 iface.addNetwork((SupplicantStatus status,
1358                         ISupplicantNetwork network) -> {
1359                     if (checkStatusAndLogFailure(status, methodStr)) {
1360                         newNetwork.value = network;
1361                     }
1362                 });
1363             } catch (RemoteException e) {
1364                 handleRemoteException(e, methodStr);
1365             }
1366             if (newNetwork.value != null) {
1367                 return getStaNetworkMockable(
1368                         ifaceName,
1369                         ISupplicantStaNetwork.asInterface(newNetwork.value.asBinder()));
1370             } else {
1371                 return null;
1372             }
1373         }
1374     }
1375 
1376     /**
1377      * Remove network from supplicant with network Id
1378      *
1379      * @return true if request is sent successfully, false otherwise.
1380      */
removeNetwork(@onNull String ifaceName, int id)1381     private boolean removeNetwork(@NonNull String ifaceName, int id) {
1382         synchronized (mLock) {
1383             final String methodStr = "removeNetwork";
1384             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1385             if (iface == null) return false;
1386             try {
1387                 SupplicantStatus status = iface.removeNetwork(id);
1388                 return checkStatusAndLogFailure(status, methodStr);
1389             } catch (RemoteException e) {
1390                 handleRemoteException(e, methodStr);
1391                 return false;
1392             }
1393         }
1394     }
1395 
1396     /**
1397      * Use this to mock the creation of SupplicantStaNetworkHal instance.
1398      *
1399      * @param ifaceName Name of the interface.
1400      * @param iSupplicantStaNetwork ISupplicantStaNetwork instance retrieved from HIDL.
1401      * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if
1402      * the call fails
1403      */
getStaNetworkMockable( @onNull String ifaceName, ISupplicantStaNetwork iSupplicantStaNetwork)1404     protected SupplicantStaNetworkHalHidlImpl getStaNetworkMockable(
1405             @NonNull String ifaceName, ISupplicantStaNetwork iSupplicantStaNetwork) {
1406         synchronized (mLock) {
1407             SupplicantStaNetworkHalHidlImpl network =
1408                     new SupplicantStaNetworkHalHidlImpl(iSupplicantStaNetwork, ifaceName, mContext,
1409                             mWifiMonitor, mWifiGlobals, getAdvancedCapabilities(ifaceName));
1410             if (network != null) {
1411                 network.enableVerboseLogging(mVerboseLoggingEnabled, mVerboseHalLoggingEnabled);
1412             }
1413             return network;
1414         }
1415     }
1416 
1417     /**
1418      * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if
1419      * the call fails
1420      */
getNetwork(@onNull String ifaceName, int id)1421     private SupplicantStaNetworkHalHidlImpl getNetwork(@NonNull String ifaceName, int id) {
1422         synchronized (mLock) {
1423             final String methodStr = "getNetwork";
1424             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1425             if (iface == null) return null;
1426             Mutable<ISupplicantNetwork> gotNetwork = new Mutable<>();
1427             try {
1428                 iface.getNetwork(id, (SupplicantStatus status, ISupplicantNetwork network) -> {
1429                     if (checkStatusAndLogFailure(status, methodStr)) {
1430                         gotNetwork.value = network;
1431                     }
1432                 });
1433             } catch (RemoteException e) {
1434                 handleRemoteException(e, methodStr);
1435             }
1436             if (gotNetwork.value != null) {
1437                 return getStaNetworkMockable(
1438                         ifaceName,
1439                         ISupplicantStaNetwork.asInterface(gotNetwork.value.asBinder()));
1440             } else {
1441                 return null;
1442             }
1443         }
1444     }
1445 
1446     /** See ISupplicantStaNetwork.hal for documentation */
registerCallback( ISupplicantStaIface iface, ISupplicantStaIfaceCallback callback)1447     private boolean registerCallback(
1448             ISupplicantStaIface iface, ISupplicantStaIfaceCallback callback) {
1449         synchronized (mLock) {
1450             final String methodStr = "registerCallback";
1451             if (iface == null) return false;
1452             try {
1453                 SupplicantStatus status =  iface.registerCallback(callback);
1454                 return checkStatusAndLogFailure(status, methodStr);
1455             } catch (RemoteException e) {
1456                 handleRemoteException(e, methodStr);
1457                 return false;
1458             }
1459         }
1460     }
1461 
registerCallbackV1_1( android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface iface, android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback callback)1462     private boolean registerCallbackV1_1(
1463             android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface iface,
1464             android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback callback) {
1465         synchronized (mLock) {
1466             String methodStr = "registerCallback_1_1";
1467 
1468             if (iface == null) return false;
1469             try {
1470                 SupplicantStatus status =  iface.registerCallback_1_1(callback);
1471                 return checkStatusAndLogFailure(status, methodStr);
1472             } catch (RemoteException e) {
1473                 handleRemoteException(e, methodStr);
1474                 return false;
1475             }
1476         }
1477     }
1478 
registerCallbackV1_2( android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface iface, android.hardware.wifi.supplicant.V1_2.ISupplicantStaIfaceCallback callback)1479     private boolean registerCallbackV1_2(
1480             android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface iface,
1481             android.hardware.wifi.supplicant.V1_2.ISupplicantStaIfaceCallback callback) {
1482         synchronized (mLock) {
1483             String methodStr = "registerCallback_1_2";
1484 
1485             if (iface == null) return false;
1486             try {
1487                 SupplicantStatus status =  iface.registerCallback_1_2(callback);
1488                 return checkStatusAndLogFailure(status, methodStr);
1489             } catch (RemoteException e) {
1490                 handleRemoteException(e, methodStr);
1491                 return false;
1492             }
1493         }
1494     }
1495 
registerCallbackV1_3( android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface iface, android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback callback)1496     private boolean registerCallbackV1_3(
1497             android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface iface,
1498             android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback callback) {
1499         synchronized (mLock) {
1500             String methodStr = "registerCallback_1_3";
1501 
1502             if (iface == null) return false;
1503             try {
1504                 SupplicantStatus status =  iface.registerCallback_1_3(callback);
1505                 return checkStatusAndLogFailure(status, methodStr);
1506             } catch (RemoteException e) {
1507                 handleRemoteException(e, methodStr);
1508                 return false;
1509             }
1510         }
1511     }
1512 
registerCallbackV1_4( android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface iface, android.hardware.wifi.supplicant.V1_4.ISupplicantStaIfaceCallback callback)1513     private boolean registerCallbackV1_4(
1514             android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface iface,
1515             android.hardware.wifi.supplicant.V1_4.ISupplicantStaIfaceCallback callback) {
1516         synchronized (mLock) {
1517             String methodStr = "registerCallback_1_4";
1518 
1519             if (iface == null) return false;
1520             try {
1521                 android.hardware.wifi.supplicant.V1_4.SupplicantStatus status =
1522                         iface.registerCallback_1_4(callback);
1523                 return checkStatusAndLogFailure(status, methodStr);
1524             } catch (RemoteException e) {
1525                 handleRemoteException(e, methodStr);
1526                 return false;
1527             }
1528         }
1529     }
1530 
1531     /**
1532      * @return a list of SupplicantNetworkID ints for all networks controlled by supplicant, returns
1533      * null if the call fails
1534      */
listNetworks(@onNull String ifaceName)1535     private java.util.ArrayList<Integer> listNetworks(@NonNull String ifaceName) {
1536         synchronized (mLock) {
1537             final String methodStr = "listNetworks";
1538             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1539             if (iface == null) return null;
1540             Mutable<ArrayList<Integer>> networkIdList = new Mutable<>();
1541             try {
1542                 iface.listNetworks((SupplicantStatus status, ArrayList<Integer> networkIds) -> {
1543                     if (checkStatusAndLogFailure(status, methodStr)) {
1544                         networkIdList.value = networkIds;
1545                     }
1546                 });
1547             } catch (RemoteException e) {
1548                 handleRemoteException(e, methodStr);
1549             }
1550             return networkIdList.value;
1551         }
1552     }
1553 
1554     /**
1555      * Set WPS device name.
1556      *
1557      * @param ifaceName Name of the interface.
1558      * @param name String to be set.
1559      * @return true if request is sent successfully, false otherwise.
1560      */
setWpsDeviceName(@onNull String ifaceName, String name)1561     public boolean setWpsDeviceName(@NonNull String ifaceName, String name) {
1562         synchronized (mLock) {
1563             final String methodStr = "setWpsDeviceName";
1564             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1565             if (iface == null) return false;
1566             try {
1567                 SupplicantStatus status = iface.setWpsDeviceName(name);
1568                 return checkStatusAndLogFailure(status, methodStr);
1569             } catch (RemoteException e) {
1570                 handleRemoteException(e, methodStr);
1571                 return false;
1572             }
1573         }
1574     }
1575 
1576     /**
1577      * Set WPS device type.
1578      *
1579      * @param ifaceName Name of the interface.
1580      * @param typeStr Type specified as a string. Used format: <categ>-<OUI>-<subcateg>
1581      * @return true if request is sent successfully, false otherwise.
1582      */
setWpsDeviceType(@onNull String ifaceName, String typeStr)1583     public boolean setWpsDeviceType(@NonNull String ifaceName, String typeStr) {
1584         synchronized (mLock) {
1585             try {
1586                 Matcher match = WPS_DEVICE_TYPE_PATTERN.matcher(typeStr);
1587                 if (!match.find() || match.groupCount() != 3) {
1588                     Log.e(TAG, "Malformed WPS device type " + typeStr);
1589                     return false;
1590                 }
1591                 short categ = Short.parseShort(match.group(1));
1592                 byte[] oui = NativeUtil.hexStringToByteArray(match.group(2));
1593                 short subCateg = Short.parseShort(match.group(3));
1594 
1595                 byte[] bytes = new byte[8];
1596                 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
1597                 byteBuffer.putShort(categ);
1598                 byteBuffer.put(oui);
1599                 byteBuffer.putShort(subCateg);
1600                 return setWpsDeviceType(ifaceName, bytes);
1601             } catch (IllegalArgumentException e) {
1602                 Log.e(TAG, "Illegal argument " + typeStr, e);
1603                 return false;
1604             }
1605         }
1606     }
1607 
setWpsDeviceType(@onNull String ifaceName, byte[ ] type)1608     private boolean setWpsDeviceType(@NonNull String ifaceName, byte[/* 8 */] type) {
1609         synchronized (mLock) {
1610             final String methodStr = "setWpsDeviceType";
1611             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1612             if (iface == null) return false;
1613             try {
1614                 SupplicantStatus status = iface.setWpsDeviceType(type);
1615                 return checkStatusAndLogFailure(status, methodStr);
1616             } catch (RemoteException e) {
1617                 handleRemoteException(e, methodStr);
1618                 return false;
1619             }
1620         }
1621     }
1622 
1623     /**
1624      * Set WPS manufacturer.
1625      *
1626      * @param ifaceName Name of the interface.
1627      * @param manufacturer String to be set.
1628      * @return true if request is sent successfully, false otherwise.
1629      */
setWpsManufacturer(@onNull String ifaceName, String manufacturer)1630     public boolean setWpsManufacturer(@NonNull String ifaceName, String manufacturer) {
1631         synchronized (mLock) {
1632             final String methodStr = "setWpsManufacturer";
1633             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1634             if (iface == null) return false;
1635             try {
1636                 SupplicantStatus status = iface.setWpsManufacturer(manufacturer);
1637                 return checkStatusAndLogFailure(status, methodStr);
1638             } catch (RemoteException e) {
1639                 handleRemoteException(e, methodStr);
1640                 return false;
1641             }
1642         }
1643     }
1644 
1645     /**
1646      * Set WPS model name.
1647      *
1648      * @param ifaceName Name of the interface.
1649      * @param modelName String to be set.
1650      * @return true if request is sent successfully, false otherwise.
1651      */
setWpsModelName(@onNull String ifaceName, String modelName)1652     public boolean setWpsModelName(@NonNull String ifaceName, String modelName) {
1653         synchronized (mLock) {
1654             final String methodStr = "setWpsModelName";
1655             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1656             if (iface == null) return false;
1657             try {
1658                 SupplicantStatus status = iface.setWpsModelName(modelName);
1659                 return checkStatusAndLogFailure(status, methodStr);
1660             } catch (RemoteException e) {
1661                 handleRemoteException(e, methodStr);
1662                 return false;
1663             }
1664         }
1665     }
1666 
1667     /**
1668      * Set WPS model number.
1669      *
1670      * @param ifaceName Name of the interface.
1671      * @param modelNumber String to be set.
1672      * @return true if request is sent successfully, false otherwise.
1673      */
setWpsModelNumber(@onNull String ifaceName, String modelNumber)1674     public boolean setWpsModelNumber(@NonNull String ifaceName, String modelNumber) {
1675         synchronized (mLock) {
1676             final String methodStr = "setWpsModelNumber";
1677             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1678             if (iface == null) return false;
1679             try {
1680                 SupplicantStatus status = iface.setWpsModelNumber(modelNumber);
1681                 return checkStatusAndLogFailure(status, methodStr);
1682             } catch (RemoteException e) {
1683                 handleRemoteException(e, methodStr);
1684                 return false;
1685             }
1686         }
1687     }
1688 
1689     /**
1690      * Set WPS serial number.
1691      *
1692      * @param ifaceName Name of the interface.
1693      * @param serialNumber String to be set.
1694      * @return true if request is sent successfully, false otherwise.
1695      */
setWpsSerialNumber(@onNull String ifaceName, String serialNumber)1696     public boolean setWpsSerialNumber(@NonNull String ifaceName, String serialNumber) {
1697         synchronized (mLock) {
1698             final String methodStr = "setWpsSerialNumber";
1699             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1700             if (iface == null) return false;
1701             try {
1702                 SupplicantStatus status = iface.setWpsSerialNumber(serialNumber);
1703                 return checkStatusAndLogFailure(status, methodStr);
1704             } catch (RemoteException e) {
1705                 handleRemoteException(e, methodStr);
1706                 return false;
1707             }
1708         }
1709     }
1710 
1711     /**
1712      * Set WPS config methods
1713      *
1714      * @param ifaceName Name of the interface.
1715      * @param configMethodsStr List of config methods.
1716      * @return true if request is sent successfully, false otherwise.
1717      */
setWpsConfigMethods(@onNull String ifaceName, String configMethodsStr)1718     public boolean setWpsConfigMethods(@NonNull String ifaceName, String configMethodsStr) {
1719         synchronized (mLock) {
1720             short configMethodsMask = 0;
1721             String[] configMethodsStrArr = configMethodsStr.split("\\s+");
1722             for (int i = 0; i < configMethodsStrArr.length; i++) {
1723                 configMethodsMask |= stringToWpsConfigMethod(configMethodsStrArr[i]);
1724             }
1725             return setWpsConfigMethods(ifaceName, configMethodsMask);
1726         }
1727     }
1728 
setWpsConfigMethods(@onNull String ifaceName, short configMethods)1729     private boolean setWpsConfigMethods(@NonNull String ifaceName, short configMethods) {
1730         synchronized (mLock) {
1731             final String methodStr = "setWpsConfigMethods";
1732             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1733             if (iface == null) return false;
1734             try {
1735                 SupplicantStatus status = iface.setWpsConfigMethods(configMethods);
1736                 return checkStatusAndLogFailure(status, methodStr);
1737             } catch (RemoteException e) {
1738                 handleRemoteException(e, methodStr);
1739                 return false;
1740             }
1741         }
1742     }
1743 
1744     /**
1745      * Trigger a reassociation even if the iface is currently connected.
1746      *
1747      * @param ifaceName Name of the interface.
1748      * @return true if request is sent successfully, false otherwise.
1749      */
reassociate(@onNull String ifaceName)1750     public boolean reassociate(@NonNull String ifaceName) {
1751         synchronized (mLock) {
1752             final String methodStr = "reassociate";
1753             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1754             if (iface == null) return false;
1755             try {
1756                 SupplicantStatus status = iface.reassociate();
1757                 return checkStatusAndLogFailure(status, methodStr);
1758             } catch (RemoteException e) {
1759                 handleRemoteException(e, methodStr);
1760                 return false;
1761             }
1762         }
1763     }
1764 
1765     /**
1766      * Trigger a reconnection if the iface is disconnected.
1767      *
1768      * @param ifaceName Name of the interface.
1769      * @return true if request is sent successfully, false otherwise.
1770      */
reconnect(@onNull String ifaceName)1771     public boolean reconnect(@NonNull String ifaceName) {
1772         synchronized (mLock) {
1773             final String methodStr = "reconnect";
1774             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1775             if (iface == null) return false;
1776             try {
1777                 SupplicantStatus status = iface.reconnect();
1778                 return checkStatusAndLogFailure(status, methodStr);
1779             } catch (RemoteException e) {
1780                 handleRemoteException(e, methodStr);
1781                 return false;
1782             }
1783         }
1784     }
1785 
1786     /**
1787      * Trigger a disconnection from the currently connected network.
1788      *
1789      * @param ifaceName Name of the interface.
1790      * @return true if request is sent successfully, false otherwise.
1791      */
disconnect(@onNull String ifaceName)1792     public boolean disconnect(@NonNull String ifaceName) {
1793         synchronized (mLock) {
1794             final String methodStr = "disconnect";
1795             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1796             if (iface == null) return false;
1797             try {
1798                 SupplicantStatus status = iface.disconnect();
1799                 return checkStatusAndLogFailure(status, methodStr);
1800             } catch (RemoteException e) {
1801                 handleRemoteException(e, methodStr);
1802                 return false;
1803             }
1804         }
1805     }
1806 
1807     /**
1808      * Enable or disable power save mode.
1809      *
1810      * @param ifaceName Name of the interface.
1811      * @param enable true to enable, false to disable.
1812      * @return true if request is sent successfully, false otherwise.
1813      */
setPowerSave(@onNull String ifaceName, boolean enable)1814     public boolean setPowerSave(@NonNull String ifaceName, boolean enable) {
1815         synchronized (mLock) {
1816             final String methodStr = "setPowerSave";
1817             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1818             if (iface == null) return false;
1819             try {
1820                 SupplicantStatus status = iface.setPowerSave(enable);
1821                 return checkStatusAndLogFailure(status, methodStr);
1822             } catch (RemoteException e) {
1823                 handleRemoteException(e, methodStr);
1824                 return false;
1825             }
1826         }
1827     }
1828 
1829     /**
1830      * Initiate TDLS discover with the specified AP.
1831      *
1832      * @param ifaceName Name of the interface.
1833      * @param macAddress MAC Address of the AP.
1834      * @return true if request is sent successfully, false otherwise.
1835      */
initiateTdlsDiscover(@onNull String ifaceName, String macAddress)1836     public boolean initiateTdlsDiscover(@NonNull String ifaceName, String macAddress) {
1837         synchronized (mLock) {
1838             try {
1839                 return initiateTdlsDiscover(
1840                         ifaceName, NativeUtil.macAddressToByteArray(macAddress));
1841             } catch (IllegalArgumentException e) {
1842                 Log.e(TAG, "Illegal argument " + macAddress, e);
1843                 return false;
1844             }
1845         }
1846     }
1847     /** See ISupplicantStaIface.hal for documentation */
initiateTdlsDiscover(@onNull String ifaceName, byte[ ] macAddress)1848     private boolean initiateTdlsDiscover(@NonNull String ifaceName, byte[/* 6 */] macAddress) {
1849         synchronized (mLock) {
1850             final String methodStr = "initiateTdlsDiscover";
1851             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1852             if (iface == null) return false;
1853             try {
1854                 SupplicantStatus status = iface.initiateTdlsDiscover(macAddress);
1855                 return checkStatusAndLogFailure(status, methodStr);
1856             } catch (RemoteException e) {
1857                 handleRemoteException(e, methodStr);
1858                 return false;
1859             }
1860         }
1861     }
1862 
1863     /**
1864      * Initiate TDLS setup with the specified AP.
1865      *
1866      * @param ifaceName Name of the interface.
1867      * @param macAddress MAC Address of the AP.
1868      * @return true if request is sent successfully, false otherwise.
1869      */
initiateTdlsSetup(@onNull String ifaceName, String macAddress)1870     public boolean initiateTdlsSetup(@NonNull String ifaceName, String macAddress) {
1871         synchronized (mLock) {
1872             try {
1873                 return initiateTdlsSetup(ifaceName, NativeUtil.macAddressToByteArray(macAddress));
1874             } catch (IllegalArgumentException e) {
1875                 Log.e(TAG, "Illegal argument " + macAddress, e);
1876                 return false;
1877             }
1878         }
1879     }
1880     /** See ISupplicantStaIface.hal for documentation */
initiateTdlsSetup(@onNull String ifaceName, byte[ ] macAddress)1881     private boolean initiateTdlsSetup(@NonNull String ifaceName, byte[/* 6 */] macAddress) {
1882         synchronized (mLock) {
1883             final String methodStr = "initiateTdlsSetup";
1884             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1885             if (iface == null) return false;
1886             try {
1887                 SupplicantStatus status = iface.initiateTdlsSetup(macAddress);
1888                 return checkStatusAndLogFailure(status, methodStr);
1889             } catch (RemoteException e) {
1890                 handleRemoteException(e, methodStr);
1891                 return false;
1892             }
1893         }
1894     }
1895 
1896     /**
1897      * Initiate TDLS teardown with the specified AP.
1898      * @param ifaceName Name of the interface.
1899      * @param macAddress MAC Address of the AP.
1900      * @return true if request is sent successfully, false otherwise.
1901      */
initiateTdlsTeardown(@onNull String ifaceName, String macAddress)1902     public boolean initiateTdlsTeardown(@NonNull String ifaceName, String macAddress) {
1903         synchronized (mLock) {
1904             try {
1905                 return initiateTdlsTeardown(
1906                         ifaceName, NativeUtil.macAddressToByteArray(macAddress));
1907             } catch (IllegalArgumentException e) {
1908                 Log.e(TAG, "Illegal argument " + macAddress, e);
1909                 return false;
1910             }
1911         }
1912     }
1913 
1914     /** See ISupplicantStaIface.hal for documentation */
initiateTdlsTeardown(@onNull String ifaceName, byte[ ] macAddress)1915     private boolean initiateTdlsTeardown(@NonNull String ifaceName, byte[/* 6 */] macAddress) {
1916         synchronized (mLock) {
1917             final String methodStr = "initiateTdlsTeardown";
1918             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1919             if (iface == null) return false;
1920             try {
1921                 SupplicantStatus status = iface.initiateTdlsTeardown(macAddress);
1922                 return checkStatusAndLogFailure(status, methodStr);
1923             } catch (RemoteException e) {
1924                 handleRemoteException(e, methodStr);
1925                 return false;
1926             }
1927         }
1928     }
1929 
1930     /**
1931      * Request the specified ANQP elements |elements| from the specified AP |bssid|.
1932      *
1933      * @param ifaceName Name of the interface.
1934      * @param bssid BSSID of the AP
1935      * @param infoElements ANQP elements to be queried. Refer to ISupplicantStaIface.AnqpInfoId.
1936      * @param hs20SubTypes HS subtypes to be queried. Refer to ISupplicantStaIface.Hs20AnqpSubTypes.
1937      * @return true if request is sent successfully, false otherwise.
1938      */
initiateAnqpQuery(@onNull String ifaceName, String bssid, ArrayList<Short> infoElements, ArrayList<Integer> hs20SubTypes)1939     public boolean initiateAnqpQuery(@NonNull String ifaceName, String bssid,
1940             ArrayList<Short> infoElements,
1941             ArrayList<Integer> hs20SubTypes) {
1942         synchronized (mLock) {
1943             try {
1944                 return initiateAnqpQuery(
1945                         ifaceName,
1946                         NativeUtil.macAddressToByteArray(bssid), infoElements, hs20SubTypes);
1947             } catch (IllegalArgumentException e) {
1948                 Log.e(TAG, "Illegal argument " + bssid, e);
1949                 return false;
1950             }
1951         }
1952     }
1953 
1954     /** See ISupplicantStaIface.hal for documentation */
initiateAnqpQuery(@onNull String ifaceName, byte[ ] macAddress, java.util.ArrayList<Short> infoElements, java.util.ArrayList<Integer> subTypes)1955     private boolean initiateAnqpQuery(@NonNull String ifaceName, byte[/* 6 */] macAddress,
1956             java.util.ArrayList<Short> infoElements, java.util.ArrayList<Integer> subTypes) {
1957         synchronized (mLock) {
1958             final String methodStr = "initiateAnqpQuery";
1959             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
1960             if (iface == null) return false;
1961             try {
1962                 SupplicantStatus status = iface.initiateAnqpQuery(
1963                         macAddress, infoElements, subTypes);
1964                 return checkStatusAndLogFailure(status, methodStr);
1965             } catch (RemoteException e) {
1966                 handleRemoteException(e, methodStr);
1967                 return false;
1968             }
1969         }
1970     }
1971 
1972     /**
1973      * Request Venue URL ANQP element from the specified AP |bssid|.
1974      *
1975      * @param ifaceName Name of the interface.
1976      * @param bssid BSSID of the AP
1977      * @return true if request is sent successfully, false otherwise.
1978      */
initiateVenueUrlAnqpQuery(@onNull String ifaceName, String bssid)1979     public boolean initiateVenueUrlAnqpQuery(@NonNull String ifaceName, String bssid) {
1980         synchronized (mLock) {
1981             try {
1982                 return initiateVenueUrlAnqpQuery(
1983                         ifaceName, NativeUtil.macAddressToByteArray(bssid));
1984             } catch (IllegalArgumentException e) {
1985                 Log.e(TAG, "Illegal argument " + bssid, e);
1986                 return false;
1987             }
1988         }
1989     }
1990 
1991     /** See ISupplicantStaIface.hal for documentation */
initiateVenueUrlAnqpQuery(@onNull String ifaceName, byte[ ] macAddress)1992     private boolean initiateVenueUrlAnqpQuery(@NonNull String ifaceName, byte[/* 6 */] macAddress) {
1993         synchronized (mLock) {
1994             final String methodStr = "initiateVenueUrlAnqpQuery";
1995             if (!isV1_4()) {
1996                 Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
1997                 return false;
1998             }
1999             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2000             // Get a v1.4 supplicant STA Interface
2001             android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface staIfaceV14 =
2002                     getStaIfaceMockableV1_4(iface);
2003 
2004             if (staIfaceV14 == null) {
2005                 Log.e(TAG, methodStr
2006                         + ": SupplicantStaIface is null, cannot initiate Venue URL ANQP request");
2007                 return false;
2008             }
2009             try {
2010                 android.hardware.wifi.supplicant.V1_4.SupplicantStatus status =
2011                         staIfaceV14.initiateVenueUrlAnqpQuery(macAddress);
2012                 return checkStatusAndLogFailure(status, methodStr);
2013             } catch (RemoteException e) {
2014                 handleRemoteException(e, methodStr);
2015                 return false;
2016             }
2017         }
2018     }
2019 
2020     /**
2021      * Request the specified ANQP ICON from the specified AP |bssid|.
2022      *
2023      * @param ifaceName Name of the interface.
2024      * @param bssid BSSID of the AP
2025      * @param fileName Name of the file to request.
2026      * @return true if request is sent successfully, false otherwise.
2027      */
initiateHs20IconQuery(@onNull String ifaceName, String bssid, String fileName)2028     public boolean initiateHs20IconQuery(@NonNull String ifaceName, String bssid, String fileName) {
2029         synchronized (mLock) {
2030             try {
2031                 return initiateHs20IconQuery(
2032                         ifaceName, NativeUtil.macAddressToByteArray(bssid), fileName);
2033             } catch (IllegalArgumentException e) {
2034                 Log.e(TAG, "Illegal argument " + bssid, e);
2035                 return false;
2036             }
2037         }
2038     }
2039 
2040     /** See ISupplicantStaIface.hal for documentation */
initiateHs20IconQuery(@onNull String ifaceName, byte[ ] macAddress, String fileName)2041     private boolean initiateHs20IconQuery(@NonNull String ifaceName,
2042             byte[/* 6 */] macAddress, String fileName) {
2043         synchronized (mLock) {
2044             final String methodStr = "initiateHs20IconQuery";
2045             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2046             if (iface == null) return false;
2047             try {
2048                 SupplicantStatus status = iface.initiateHs20IconQuery(macAddress, fileName);
2049                 return checkStatusAndLogFailure(status, methodStr);
2050             } catch (RemoteException e) {
2051                 handleRemoteException(e, methodStr);
2052                 return false;
2053             }
2054         }
2055     }
2056 
2057     /**
2058      * Makes a callback to HIDL to getMacAddress from supplicant
2059      *
2060      * @param ifaceName Name of the interface.
2061      * @return string containing the MAC address, or null on a failed call
2062      */
getMacAddress(@onNull String ifaceName)2063     public String getMacAddress(@NonNull String ifaceName) {
2064         synchronized (mLock) {
2065             final String methodStr = "getMacAddress";
2066             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2067             if (iface == null) return null;
2068             Mutable<String> gotMac = new Mutable<>();
2069             try {
2070                 iface.getMacAddress((SupplicantStatus status,
2071                         byte[/* 6 */] macAddr) -> {
2072                     if (checkStatusAndLogFailure(status, methodStr)) {
2073                         gotMac.value = NativeUtil.macAddressFromByteArray(macAddr);
2074                     }
2075                 });
2076             } catch (RemoteException e) {
2077                 handleRemoteException(e, methodStr);
2078             }
2079             return gotMac.value;
2080         }
2081     }
2082 
2083     /**
2084      * Start using the added RX filters.
2085      *
2086      * @param ifaceName Name of the interface.
2087      * @return true if request is sent successfully, false otherwise.
2088      */
startRxFilter(@onNull String ifaceName)2089     public boolean startRxFilter(@NonNull String ifaceName) {
2090         synchronized (mLock) {
2091             final String methodStr = "startRxFilter";
2092             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2093             if (iface == null) return false;
2094             try {
2095                 SupplicantStatus status = iface.startRxFilter();
2096                 return checkStatusAndLogFailure(status, methodStr);
2097             } catch (RemoteException e) {
2098                 handleRemoteException(e, methodStr);
2099                 return false;
2100             }
2101         }
2102     }
2103 
2104     /**
2105      * Stop using the added RX filters.
2106      *
2107      * @param ifaceName Name of the interface.
2108      * @return true if request is sent successfully, false otherwise.
2109      */
stopRxFilter(@onNull String ifaceName)2110     public boolean stopRxFilter(@NonNull String ifaceName) {
2111         synchronized (mLock) {
2112             final String methodStr = "stopRxFilter";
2113             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2114             if (iface == null) return false;
2115             try {
2116                 SupplicantStatus status = iface.stopRxFilter();
2117                 return checkStatusAndLogFailure(status, methodStr);
2118             } catch (RemoteException e) {
2119                 handleRemoteException(e, methodStr);
2120                 return false;
2121             }
2122         }
2123     }
2124 
2125     /**
2126      * Add an RX filter.
2127      *
2128      * @param ifaceName Name of the interface.
2129      * @param type one of {@link WifiNative#RX_FILTER_TYPE_V4_MULTICAST}
2130      *        {@link WifiNative#RX_FILTER_TYPE_V6_MULTICAST} values.
2131      * @return true if request is sent successfully, false otherwise.
2132      */
addRxFilter(@onNull String ifaceName, int type)2133     public boolean addRxFilter(@NonNull String ifaceName, int type) {
2134         synchronized (mLock) {
2135             byte halType;
2136             switch (type) {
2137                 case WifiNative.RX_FILTER_TYPE_V4_MULTICAST:
2138                     halType = ISupplicantStaIface.RxFilterType.V4_MULTICAST;
2139                     break;
2140                 case WifiNative.RX_FILTER_TYPE_V6_MULTICAST:
2141                     halType = ISupplicantStaIface.RxFilterType.V6_MULTICAST;
2142                     break;
2143                 default:
2144                     Log.e(TAG, "Invalid Rx Filter type: " + type);
2145                     return false;
2146             }
2147             return addRxFilter(ifaceName, halType);
2148         }
2149     }
2150 
addRxFilter(@onNull String ifaceName, byte type)2151     private boolean addRxFilter(@NonNull String ifaceName, byte type) {
2152         synchronized (mLock) {
2153             final String methodStr = "addRxFilter";
2154             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2155             if (iface == null) return false;
2156             try {
2157                 SupplicantStatus status = iface.addRxFilter(type);
2158                 return checkStatusAndLogFailure(status, methodStr);
2159             } catch (RemoteException e) {
2160                 handleRemoteException(e, methodStr);
2161                 return false;
2162             }
2163         }
2164     }
2165 
2166     /**
2167      * Remove an RX filter.
2168      *
2169      * @param ifaceName Name of the interface.
2170      * @param type one of {@link WifiNative#RX_FILTER_TYPE_V4_MULTICAST}
2171      *        {@link WifiNative#RX_FILTER_TYPE_V6_MULTICAST} values.
2172      * @return true if request is sent successfully, false otherwise.
2173      */
removeRxFilter(@onNull String ifaceName, int type)2174     public boolean removeRxFilter(@NonNull String ifaceName, int type) {
2175         synchronized (mLock) {
2176             byte halType;
2177             switch (type) {
2178                 case WifiNative.RX_FILTER_TYPE_V4_MULTICAST:
2179                     halType = ISupplicantStaIface.RxFilterType.V4_MULTICAST;
2180                     break;
2181                 case WifiNative.RX_FILTER_TYPE_V6_MULTICAST:
2182                     halType = ISupplicantStaIface.RxFilterType.V6_MULTICAST;
2183                     break;
2184                 default:
2185                     Log.e(TAG, "Invalid Rx Filter type: " + type);
2186                     return false;
2187             }
2188             return removeRxFilter(ifaceName, halType);
2189         }
2190     }
2191 
removeRxFilter(@onNull String ifaceName, byte type)2192     private boolean removeRxFilter(@NonNull String ifaceName, byte type) {
2193         synchronized (mLock) {
2194             final String methodStr = "removeRxFilter";
2195             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2196             if (iface == null) return false;
2197             try {
2198                 SupplicantStatus status = iface.removeRxFilter(type);
2199                 return checkStatusAndLogFailure(status, methodStr);
2200             } catch (RemoteException e) {
2201                 handleRemoteException(e, methodStr);
2202                 return false;
2203             }
2204         }
2205     }
2206 
2207     /**
2208      * Set Bt co existense mode.
2209      *
2210      * @param ifaceName Name of the interface.
2211      * @param mode one of the above {@link WifiNative#BLUETOOTH_COEXISTENCE_MODE_DISABLED},
2212      *             {@link WifiNative#BLUETOOTH_COEXISTENCE_MODE_ENABLED} or
2213      *             {@link WifiNative#BLUETOOTH_COEXISTENCE_MODE_SENSE}.
2214      * @return true if request is sent successfully, false otherwise.
2215      */
setBtCoexistenceMode(@onNull String ifaceName, int mode)2216     public boolean setBtCoexistenceMode(@NonNull String ifaceName, int mode) {
2217         synchronized (mLock) {
2218             byte halMode;
2219             switch (mode) {
2220                 case WifiNative.BLUETOOTH_COEXISTENCE_MODE_ENABLED:
2221                     halMode = ISupplicantStaIface.BtCoexistenceMode.ENABLED;
2222                     break;
2223                 case WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED:
2224                     halMode = ISupplicantStaIface.BtCoexistenceMode.DISABLED;
2225                     break;
2226                 case WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE:
2227                     halMode = ISupplicantStaIface.BtCoexistenceMode.SENSE;
2228                     break;
2229                 default:
2230                     Log.e(TAG, "Invalid Bt Coex mode: " + mode);
2231                     return false;
2232             }
2233             return setBtCoexistenceMode(ifaceName, halMode);
2234         }
2235     }
2236 
setBtCoexistenceMode(@onNull String ifaceName, byte mode)2237     private boolean setBtCoexistenceMode(@NonNull String ifaceName, byte mode) {
2238         synchronized (mLock) {
2239             final String methodStr = "setBtCoexistenceMode";
2240             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2241             if (iface == null) return false;
2242             try {
2243                 SupplicantStatus status = iface.setBtCoexistenceMode(mode);
2244                 return checkStatusAndLogFailure(status, methodStr);
2245             } catch (RemoteException e) {
2246                 handleRemoteException(e, methodStr);
2247                 return false;
2248             }
2249         }
2250     }
2251 
2252     /** Enable or disable BT coexistence mode.
2253      *
2254      * @param ifaceName Name of the interface.
2255      * @param enable true to enable, false to disable.
2256      * @return true if request is sent successfully, false otherwise.
2257      */
setBtCoexistenceScanModeEnabled(@onNull String ifaceName, boolean enable)2258     public boolean setBtCoexistenceScanModeEnabled(@NonNull String ifaceName, boolean enable) {
2259         synchronized (mLock) {
2260             final String methodStr = "setBtCoexistenceScanModeEnabled";
2261             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2262             if (iface == null) return false;
2263             try {
2264                 SupplicantStatus status =
2265                         iface.setBtCoexistenceScanModeEnabled(enable);
2266                 return checkStatusAndLogFailure(status, methodStr);
2267             } catch (RemoteException e) {
2268                 handleRemoteException(e, methodStr);
2269                 return false;
2270             }
2271         }
2272     }
2273 
2274     /**
2275      * Enable or disable suspend mode optimizations.
2276      *
2277      * @param ifaceName Name of the interface.
2278      * @param enable true to enable, false otherwise.
2279      * @return true if request is sent successfully, false otherwise.
2280      */
setSuspendModeEnabled(@onNull String ifaceName, boolean enable)2281     public boolean setSuspendModeEnabled(@NonNull String ifaceName, boolean enable) {
2282         synchronized (mLock) {
2283             final String methodStr = "setSuspendModeEnabled";
2284             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2285             if (iface == null) return false;
2286             try {
2287                 SupplicantStatus status = iface.setSuspendModeEnabled(enable);
2288                 return checkStatusAndLogFailure(status, methodStr);
2289             } catch (RemoteException e) {
2290                 handleRemoteException(e, methodStr);
2291                 return false;
2292             }
2293         }
2294     }
2295 
2296     /**
2297      * Set country code.
2298      *
2299      * @param ifaceName Name of the interface.
2300      * @param codeStr 2 byte ASCII string. For ex: US, CA.
2301      * @return true if request is sent successfully, false otherwise.
2302      */
setCountryCode(@onNull String ifaceName, String codeStr)2303     public boolean setCountryCode(@NonNull String ifaceName, String codeStr) {
2304         synchronized (mLock) {
2305             if (TextUtils.isEmpty(codeStr)) return false;
2306             byte[] countryCodeBytes = NativeUtil.stringToByteArray(codeStr);
2307             if (countryCodeBytes.length != 2) return false;
2308             return setCountryCode(ifaceName, countryCodeBytes);
2309         }
2310     }
2311 
2312     /** See ISupplicantStaIface.hal for documentation */
setCountryCode(@onNull String ifaceName, byte[ ] code)2313     private boolean setCountryCode(@NonNull String ifaceName, byte[/* 2 */] code) {
2314         synchronized (mLock) {
2315             final String methodStr = "setCountryCode";
2316             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2317             if (iface == null) return false;
2318             try {
2319                 SupplicantStatus status = iface.setCountryCode(code);
2320                 return checkStatusAndLogFailure(status, methodStr);
2321             } catch (RemoteException e) {
2322                 handleRemoteException(e, methodStr);
2323                 return false;
2324             }
2325         }
2326     }
2327 
2328     /**
2329      * Flush all previously configured HLPs.
2330      *
2331      * @param ifaceName Name of the interface.
2332      * @return true if request is sent successfully, false otherwise.
2333      */
flushAllHlp(@onNull String ifaceName)2334     public boolean flushAllHlp(@NonNull String ifaceName) {
2335         synchronized (mLock) {
2336             final String methodStr = "filsHlpFlushRequest";
2337             if (isV1_3()) {
2338                 ISupplicantStaIface iface =
2339                         checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2340                 if (iface == null) {
2341                     return false;
2342                 }
2343 
2344                 // Get a v1.3 supplicant STA Interface
2345                 android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 =
2346                         getStaIfaceMockableV1_3(iface);
2347 
2348                 if (staIfaceV13 == null) {
2349                     Log.e(TAG, methodStr
2350                             + ": ISupplicantStaIface is null, cannot flushAllHlp");
2351                     return false;
2352                 }
2353                 try {
2354                     SupplicantStatus status = staIfaceV13.filsHlpFlushRequest();
2355                     return checkStatusAndLogFailure(status, methodStr);
2356                 } catch (RemoteException e) {
2357                     handleRemoteException(e, methodStr);
2358                     return false;
2359                 }
2360             } else {
2361                 Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
2362                 return false;
2363             }
2364         }
2365     }
2366 
2367     /**
2368      * Set FILS HLP packet.
2369      *
2370      * @param ifaceName Name of the interface.
2371      * @param dst Destination MAC address.
2372      * @param hlpPacket Hlp Packet data in hex.
2373      * @return true if request is sent successfully, false otherwise.
2374      */
addHlpReq(@onNull String ifaceName, byte [] dst, byte [] hlpPacket)2375     public boolean addHlpReq(@NonNull String ifaceName, byte [] dst, byte [] hlpPacket) {
2376         synchronized (mLock) {
2377             final String methodStr = "filsHlpAddRequest";
2378             if (isV1_3()) {
2379                 ISupplicantStaIface iface =
2380                         checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2381                 if (iface == null) {
2382                     return false;
2383                 }
2384 
2385                 // Get a v1.3 supplicant STA Interface
2386                 android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 =
2387                         getStaIfaceMockableV1_3(iface);
2388 
2389                 if (staIfaceV13 == null) {
2390                     Log.e(TAG, methodStr
2391                             + ": ISupplicantStaIface is null, cannot addHlpReq");
2392                     return false;
2393                 }
2394                 try {
2395                     ArrayList<Byte> payload = NativeUtil.byteArrayToArrayList(hlpPacket);
2396                     SupplicantStatus status = staIfaceV13.filsHlpAddRequest(dst, payload);
2397                     return checkStatusAndLogFailure(status, methodStr);
2398                 } catch (RemoteException e) {
2399                     handleRemoteException(e, methodStr);
2400                     return false;
2401                 }
2402             } else {
2403                 Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
2404                 return false;
2405             }
2406         }
2407     }
2408 
2409 
2410     /**
2411      * Start WPS pin registrar operation with the specified peer and pin.
2412      *
2413      * @param ifaceName Name of the interface.
2414      * @param bssidStr BSSID of the peer.
2415      * @param pin Pin to be used.
2416      * @return true if request is sent successfully, false otherwise.
2417      */
startWpsRegistrar(@onNull String ifaceName, String bssidStr, String pin)2418     public boolean startWpsRegistrar(@NonNull String ifaceName, String bssidStr, String pin) {
2419         synchronized (mLock) {
2420             if (TextUtils.isEmpty(bssidStr) || TextUtils.isEmpty(pin)) return false;
2421             try {
2422                 return startWpsRegistrar(
2423                         ifaceName, NativeUtil.macAddressToByteArray(bssidStr), pin);
2424             } catch (IllegalArgumentException e) {
2425                 Log.e(TAG, "Illegal argument " + bssidStr, e);
2426                 return false;
2427             }
2428         }
2429     }
2430 
2431     /** See ISupplicantStaIface.hal for documentation */
startWpsRegistrar(@onNull String ifaceName, byte[ ] bssid, String pin)2432     private boolean startWpsRegistrar(@NonNull String ifaceName, byte[/* 6 */] bssid, String pin) {
2433         synchronized (mLock) {
2434             final String methodStr = "startWpsRegistrar";
2435             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2436             if (iface == null) return false;
2437             try {
2438                 SupplicantStatus status = iface.startWpsRegistrar(bssid, pin);
2439                 return checkStatusAndLogFailure(status, methodStr);
2440             } catch (RemoteException e) {
2441                 handleRemoteException(e, methodStr);
2442                 return false;
2443             }
2444         }
2445     }
2446 
2447     /**
2448      * Start WPS pin display operation with the specified peer.
2449      *
2450      * @param ifaceName Name of the interface.
2451      * @param bssidStr BSSID of the peer. Use empty bssid to indicate wildcard.
2452      * @return true if request is sent successfully, false otherwise.
2453      */
startWpsPbc(@onNull String ifaceName, String bssidStr)2454     public boolean startWpsPbc(@NonNull String ifaceName, String bssidStr) {
2455         synchronized (mLock) {
2456             try {
2457                 return startWpsPbc(ifaceName, NativeUtil.macAddressToByteArray(bssidStr));
2458             } catch (IllegalArgumentException e) {
2459                 Log.e(TAG, "Illegal argument " + bssidStr, e);
2460                 return false;
2461             }
2462         }
2463     }
2464 
2465     /** See ISupplicantStaIface.hal for documentation */
startWpsPbc(@onNull String ifaceName, byte[ ] bssid)2466     private boolean startWpsPbc(@NonNull String ifaceName, byte[/* 6 */] bssid) {
2467         synchronized (mLock) {
2468             final String methodStr = "startWpsPbc";
2469             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2470             if (iface == null) return false;
2471             try {
2472                 SupplicantStatus status = iface.startWpsPbc(bssid);
2473                 return checkStatusAndLogFailure(status, methodStr);
2474             } catch (RemoteException e) {
2475                 handleRemoteException(e, methodStr);
2476                 return false;
2477             }
2478         }
2479     }
2480 
2481     /**
2482      * Start WPS pin keypad operation with the specified pin.
2483      *
2484      * @param ifaceName Name of the interface.
2485      * @param pin Pin to be used.
2486      * @return true if request is sent successfully, false otherwise.
2487      */
startWpsPinKeypad(@onNull String ifaceName, String pin)2488     public boolean startWpsPinKeypad(@NonNull String ifaceName, String pin) {
2489         if (TextUtils.isEmpty(pin)) return false;
2490         synchronized (mLock) {
2491             final String methodStr = "startWpsPinKeypad";
2492             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2493             if (iface == null) return false;
2494             try {
2495                 SupplicantStatus status = iface.startWpsPinKeypad(pin);
2496                 return checkStatusAndLogFailure(status, methodStr);
2497             } catch (RemoteException e) {
2498                 handleRemoteException(e, methodStr);
2499                 return false;
2500             }
2501         }
2502     }
2503 
2504     /**
2505      * Start WPS pin display operation with the specified peer.
2506      *
2507      * @param ifaceName Name of the interface.
2508      * @param bssidStr BSSID of the peer. Use empty bssid to indicate wildcard.
2509      * @return new pin generated on success, null otherwise.
2510      */
startWpsPinDisplay(@onNull String ifaceName, String bssidStr)2511     public String startWpsPinDisplay(@NonNull String ifaceName, String bssidStr) {
2512         synchronized (mLock) {
2513             try {
2514                 return startWpsPinDisplay(ifaceName, NativeUtil.macAddressToByteArray(bssidStr));
2515             } catch (IllegalArgumentException e) {
2516                 Log.e(TAG, "Illegal argument " + bssidStr, e);
2517                 return null;
2518             }
2519         }
2520     }
2521 
2522     /** See ISupplicantStaIface.hal for documentation */
startWpsPinDisplay(@onNull String ifaceName, byte[ ] bssid)2523     private String startWpsPinDisplay(@NonNull String ifaceName, byte[/* 6 */] bssid) {
2524         synchronized (mLock) {
2525             final String methodStr = "startWpsPinDisplay";
2526             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2527             if (iface == null) return null;
2528             final Mutable<String> gotPin = new Mutable<>();
2529             try {
2530                 iface.startWpsPinDisplay(bssid,
2531                         (SupplicantStatus status, String pin) -> {
2532                             if (checkStatusAndLogFailure(status, methodStr)) {
2533                                 gotPin.value = pin;
2534                             }
2535                         });
2536             } catch (RemoteException e) {
2537                 handleRemoteException(e, methodStr);
2538             }
2539             return gotPin.value;
2540         }
2541     }
2542 
2543     /**
2544      * Cancels any ongoing WPS requests.
2545      *
2546      * @param ifaceName Name of the interface.
2547      * @return true if request is sent successfully, false otherwise.
2548      */
cancelWps(@onNull String ifaceName)2549     public boolean cancelWps(@NonNull String ifaceName) {
2550         synchronized (mLock) {
2551             final String methodStr = "cancelWps";
2552             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2553             if (iface == null) return false;
2554             try {
2555                 SupplicantStatus status = iface.cancelWps();
2556                 return checkStatusAndLogFailure(status, methodStr);
2557             } catch (RemoteException e) {
2558                 handleRemoteException(e, methodStr);
2559                 return false;
2560             }
2561         }
2562     }
2563 
2564     /**
2565      * Sets whether to use external sim for SIM/USIM processing.
2566      *
2567      * @param ifaceName Name of the interface.
2568      * @param useExternalSim true to enable, false otherwise.
2569      * @return true if request is sent successfully, false otherwise.
2570      */
setExternalSim(@onNull String ifaceName, boolean useExternalSim)2571     public boolean setExternalSim(@NonNull String ifaceName, boolean useExternalSim) {
2572         synchronized (mLock) {
2573             final String methodStr = "setExternalSim";
2574             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2575             if (iface == null) return false;
2576             try {
2577                 SupplicantStatus status = iface.setExternalSim(useExternalSim);
2578                 return checkStatusAndLogFailure(status, methodStr);
2579             } catch (RemoteException e) {
2580                 handleRemoteException(e, methodStr);
2581                 return false;
2582             }
2583         }
2584     }
2585 
2586     /** See ISupplicant.hal for documentation */
enableAutoReconnect(@onNull String ifaceName, boolean enable)2587     public boolean enableAutoReconnect(@NonNull String ifaceName, boolean enable) {
2588         synchronized (mLock) {
2589             final String methodStr = "enableAutoReconnect";
2590             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2591             if (iface == null) return false;
2592             try {
2593                 SupplicantStatus status = iface.enableAutoReconnect(enable);
2594                 return checkStatusAndLogFailure(status, methodStr);
2595             } catch (RemoteException e) {
2596                 handleRemoteException(e, methodStr);
2597                 return false;
2598             }
2599         }
2600     }
2601 
2602     /**
2603      * Set the debug log level for wpa_supplicant
2604      *
2605      * @param turnOnVerbose Whether to turn on verbose logging or not.
2606      * @return true if request is sent successfully, false otherwise.
2607      */
setLogLevel(boolean turnOnVerbose)2608     public boolean setLogLevel(boolean turnOnVerbose) {
2609         synchronized (mLock) {
2610             int logLevel = turnOnVerbose
2611                     ? ISupplicant.DebugLevel.DEBUG
2612                     : ISupplicant.DebugLevel.INFO;
2613             return setDebugParams(logLevel, false,
2614                     turnOnVerbose && mWifiGlobals.getShowKeyVerboseLoggingModeEnabled());
2615         }
2616     }
2617 
2618     /** See ISupplicant.hal for documentation */
setDebugParams(int level, boolean showTimestamp, boolean showKeys)2619     private boolean setDebugParams(int level, boolean showTimestamp, boolean showKeys) {
2620         synchronized (mLock) {
2621             final String methodStr = "setDebugParams";
2622             if (!checkSupplicantAndLogFailure(methodStr)) return false;
2623             try {
2624                 SupplicantStatus status =
2625                         mISupplicant.setDebugParams(level, showTimestamp, showKeys);
2626                 return checkStatusAndLogFailure(status, methodStr);
2627             } catch (RemoteException e) {
2628                 handleRemoteException(e, methodStr);
2629                 return false;
2630             }
2631         }
2632     }
2633 
2634     /**
2635      * Set concurrency priority between P2P & STA operations.
2636      *
2637      * @param isStaHigherPriority Set to true to prefer STA over P2P during concurrency operations,
2638      *                            false otherwise.
2639      * @return true if request is sent successfully, false otherwise.
2640      */
setConcurrencyPriority(boolean isStaHigherPriority)2641     public boolean setConcurrencyPriority(boolean isStaHigherPriority) {
2642         synchronized (mLock) {
2643             if (isStaHigherPriority) {
2644                 return setConcurrencyPriority(IfaceType.STA);
2645             } else {
2646                 return setConcurrencyPriority(IfaceType.P2P);
2647             }
2648         }
2649     }
2650 
2651     /** See ISupplicant.hal for documentation */
setConcurrencyPriority(int type)2652     private boolean setConcurrencyPriority(int type) {
2653         synchronized (mLock) {
2654             final String methodStr = "setConcurrencyPriority";
2655             if (!checkSupplicantAndLogFailure(methodStr)) return false;
2656             try {
2657                 SupplicantStatus status = mISupplicant.setConcurrencyPriority(type);
2658                 return checkStatusAndLogFailure(status, methodStr);
2659             } catch (RemoteException e) {
2660                 handleRemoteException(e, methodStr);
2661                 return false;
2662             }
2663         }
2664     }
2665 
2666     /**
2667      * Returns false if Supplicant is null, and logs failure to call methodStr
2668      */
checkSupplicantAndLogFailure(final String methodStr)2669     private boolean checkSupplicantAndLogFailure(final String methodStr) {
2670         synchronized (mLock) {
2671             if (mISupplicant == null) {
2672                 Log.e(TAG, "Can't call " + methodStr + ", ISupplicant is null");
2673                 return false;
2674             }
2675             return true;
2676         }
2677     }
2678 
2679     /**
2680      * Returns false if SupplicantStaIface is null, and logs failure to call methodStr
2681      */
checkSupplicantStaIfaceAndLogFailure( @onNull String ifaceName, final String methodStr)2682     private ISupplicantStaIface checkSupplicantStaIfaceAndLogFailure(
2683             @NonNull String ifaceName, final String methodStr) {
2684         synchronized (mLock) {
2685             ISupplicantStaIface iface = getStaIface(ifaceName);
2686             if (iface == null) {
2687                 Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaIface is null for iface="
2688                         + ifaceName);
2689                 return null;
2690             }
2691             return iface;
2692         }
2693     }
2694 
2695     /**
2696      * Returns false if SupplicantStaNetwork is null, and logs failure to call methodStr
2697      */
checkSupplicantStaNetworkAndLogFailure( @onNull String ifaceName, final String methodStr)2698     private SupplicantStaNetworkHalHidlImpl checkSupplicantStaNetworkAndLogFailure(
2699             @NonNull String ifaceName, final String methodStr) {
2700         synchronized (mLock) {
2701             SupplicantStaNetworkHalHidlImpl networkHal = getCurrentNetworkRemoteHandle(ifaceName);
2702             if (networkHal == null) {
2703                 Log.e(TAG, "Can't call " + methodStr + ", SupplicantStaNetwork is null");
2704                 return null;
2705             }
2706             return networkHal;
2707         }
2708     }
2709 
2710     /**
2711      * Returns true if provided status code is SUCCESS, logs debug message and returns false
2712      * otherwise
2713      */
checkStatusAndLogFailure(SupplicantStatus status, final String methodStr)2714     private boolean checkStatusAndLogFailure(SupplicantStatus status,
2715             final String methodStr) {
2716         synchronized (mLock) {
2717             if (status == null || status.code != SupplicantStatusCode.SUCCESS) {
2718                 Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed: " + status);
2719                 return false;
2720             } else {
2721                 if (mVerboseLoggingEnabled) {
2722                     Log.d(TAG, "ISupplicantStaIface." + methodStr + " succeeded");
2723                 }
2724                 return true;
2725             }
2726         }
2727     }
2728 
2729     /**
2730      * Returns true if provided status code is SUCCESS, logs debug message and returns false
2731      * otherwise
2732      */
checkStatusAndLogFailure( android.hardware.wifi.supplicant.V1_4.SupplicantStatus status, final String methodStr)2733     private boolean checkStatusAndLogFailure(
2734             android.hardware.wifi.supplicant.V1_4.SupplicantStatus status,
2735             final String methodStr) {
2736         synchronized (mLock) {
2737             if (status == null
2738                     || status.code
2739                     != android.hardware.wifi.supplicant.V1_4.SupplicantStatusCode.SUCCESS) {
2740                 Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed: " + status);
2741                 return false;
2742             } else {
2743                 if (mVerboseLoggingEnabled) {
2744                     Log.d(TAG, "ISupplicantStaIface." + methodStr + " succeeded");
2745                 }
2746                 return true;
2747             }
2748         }
2749     }
2750 
2751     /**
2752      * Helper function to log callbacks.
2753      */
logCallback(final String methodStr)2754     protected void logCallback(final String methodStr) {
2755         synchronized (mLock) {
2756             if (mVerboseLoggingEnabled) {
2757                 Log.d(TAG, "ISupplicantStaIfaceCallback." + methodStr + " received");
2758             }
2759         }
2760     }
2761 
handleNoSuchElementException(NoSuchElementException e, String methodStr)2762     private void handleNoSuchElementException(NoSuchElementException e, String methodStr) {
2763         synchronized (mLock) {
2764             clearState();
2765             Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed with exception", e);
2766         }
2767     }
2768 
handleRemoteException(RemoteException e, String methodStr)2769     private void handleRemoteException(RemoteException e, String methodStr) {
2770         synchronized (mLock) {
2771             clearState();
2772             Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed with exception", e);
2773         }
2774     }
2775 
handleIllegalArgumentException(IllegalArgumentException e, String methodStr)2776     private void handleIllegalArgumentException(IllegalArgumentException e, String methodStr) {
2777         synchronized (mLock) {
2778             clearState();
2779             Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed with exception", e);
2780         }
2781     }
2782 
2783     /**
2784      * Converts the Wps config method string to the equivalent enum value.
2785      */
stringToWpsConfigMethod(String configMethod)2786     private static short stringToWpsConfigMethod(String configMethod) {
2787         switch (configMethod) {
2788             case "usba":
2789                 return WpsConfigMethods.USBA;
2790             case "ethernet":
2791                 return WpsConfigMethods.ETHERNET;
2792             case "label":
2793                 return WpsConfigMethods.LABEL;
2794             case "display":
2795                 return WpsConfigMethods.DISPLAY;
2796             case "int_nfc_token":
2797                 return WpsConfigMethods.INT_NFC_TOKEN;
2798             case "ext_nfc_token":
2799                 return WpsConfigMethods.EXT_NFC_TOKEN;
2800             case "nfc_interface":
2801                 return WpsConfigMethods.NFC_INTERFACE;
2802             case "push_button":
2803                 return WpsConfigMethods.PUSHBUTTON;
2804             case "keypad":
2805                 return WpsConfigMethods.KEYPAD;
2806             case "virtual_push_button":
2807                 return WpsConfigMethods.VIRT_PUSHBUTTON;
2808             case "physical_push_button":
2809                 return WpsConfigMethods.PHY_PUSHBUTTON;
2810             case "p2ps":
2811                 return WpsConfigMethods.P2PS;
2812             case "virtual_display":
2813                 return WpsConfigMethods.VIRT_DISPLAY;
2814             case "physical_display":
2815                 return WpsConfigMethods.PHY_DISPLAY;
2816             default:
2817                 throw new IllegalArgumentException(
2818                         "Invalid WPS config method: " + configMethod);
2819         }
2820     }
2821 
2822     protected class SupplicantStaIfaceHalCallback extends SupplicantStaIfaceCallbackHidlImpl {
SupplicantStaIfaceHalCallback(@onNull String ifaceName)2823         SupplicantStaIfaceHalCallback(@NonNull String ifaceName) {
2824             super(SupplicantStaIfaceHalHidlImpl.this, ifaceName, new Object(), mWifiMonitor);
2825         }
2826     }
2827 
2828     protected class SupplicantStaIfaceHalCallbackV1_1 extends
2829             SupplicantStaIfaceCallbackHidlV1_1Impl {
SupplicantStaIfaceHalCallbackV1_1(@onNull String ifaceName)2830         SupplicantStaIfaceHalCallbackV1_1(@NonNull String ifaceName) {
2831             super(SupplicantStaIfaceHalHidlImpl.this, ifaceName, new Object(), mWifiMonitor);
2832         }
2833     }
2834 
2835     protected class SupplicantStaIfaceHalCallbackV1_2 extends
2836             SupplicantStaIfaceCallbackHidlV1_2Impl {
SupplicantStaIfaceHalCallbackV1_2(@onNull String ifaceName)2837         SupplicantStaIfaceHalCallbackV1_2(@NonNull String ifaceName) {
2838             super(SupplicantStaIfaceHalHidlImpl.this, ifaceName, mContext);
2839         }
2840     }
2841 
2842     protected class SupplicantStaIfaceHalCallbackV1_3 extends
2843             SupplicantStaIfaceCallbackHidlV1_3Impl {
SupplicantStaIfaceHalCallbackV1_3(@onNull String ifaceName)2844         SupplicantStaIfaceHalCallbackV1_3(@NonNull String ifaceName) {
2845             super(SupplicantStaIfaceHalHidlImpl.this, ifaceName, mWifiMonitor);
2846         }
2847     }
2848 
2849     protected class SupplicantStaIfaceHalCallbackV1_4 extends
2850             SupplicantStaIfaceCallbackHidlV1_4Impl {
SupplicantStaIfaceHalCallbackV1_4(@onNull String ifaceName)2851         SupplicantStaIfaceHalCallbackV1_4(@NonNull String ifaceName) {
2852             super(SupplicantStaIfaceHalHidlImpl.this, ifaceName, new Object(), mWifiMonitor);
2853         }
2854     }
2855 
addPmkCacheEntry( String ifaceName, int networkId, long expirationTimeInSec, ArrayList<Byte> serializedEntry)2856     protected void addPmkCacheEntry(
2857             String ifaceName,
2858             int networkId, long expirationTimeInSec, ArrayList<Byte> serializedEntry) {
2859         String macAddressStr = getMacAddress(ifaceName);
2860         try {
2861             if (!mPmkCacheManager.add(MacAddress.fromString(macAddressStr),
2862                     networkId, expirationTimeInSec, serializedEntry)) {
2863                 Log.w(TAG, "Cannot add PMK cache for " + ifaceName);
2864             }
2865         } catch (IllegalArgumentException ex) {
2866             Log.w(TAG, "Cannot add PMK cache: " + ex);
2867         }
2868     }
2869 
removePmkCacheEntry(int networkId)2870     protected void removePmkCacheEntry(int networkId) {
2871         mPmkCacheManager.remove(networkId);
2872     }
2873 
logd(String s)2874     private static void logd(String s) {
2875         Log.d(TAG, s);
2876     }
2877 
logi(String s)2878     private static void logi(String s) {
2879         Log.i(TAG, s);
2880     }
2881 
loge(String s)2882     private static void loge(String s) {
2883         Log.e(TAG, s);
2884     }
2885 
2886     /**
2887      * Returns a bitmask of advanced capabilities: WPA3 SAE/SUITE B and OWE
2888      * Bitmask used is:
2889      * - WIFI_FEATURE_WPA3_SAE
2890      * - WIFI_FEATURE_WPA3_SUITE_B
2891      * - WIFI_FEATURE_OWE
2892      *
2893      *  This is a v1.2+ HAL feature.
2894      *  On error, or if these features are not supported, 0 is returned.
2895      */
getAdvancedCapabilities(@onNull String ifaceName)2896     public long getAdvancedCapabilities(@NonNull String ifaceName) {
2897         final String methodStr = "getAdvancedCapabilities";
2898 
2899         long advancedCapabilities = 0;
2900         int keyMgmtCapabilities = getKeyMgmtCapabilities(ifaceName);
2901 
2902         if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork
2903                 .KeyMgmtMask.SAE) != 0) {
2904             advancedCapabilities |= WIFI_FEATURE_WPA3_SAE;
2905 
2906             if (mVerboseLoggingEnabled) {
2907                 Log.v(TAG, methodStr + ": SAE supported");
2908             }
2909         }
2910 
2911         if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork
2912                 .KeyMgmtMask.SUITE_B_192) != 0) {
2913             advancedCapabilities |= WIFI_FEATURE_WPA3_SUITE_B;
2914 
2915             if (mVerboseLoggingEnabled) {
2916                 Log.v(TAG, methodStr + ": SUITE_B supported");
2917             }
2918         }
2919 
2920         if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork
2921                 .KeyMgmtMask.OWE) != 0) {
2922             advancedCapabilities |= WIFI_FEATURE_OWE;
2923 
2924             if (mVerboseLoggingEnabled) {
2925                 Log.v(TAG, methodStr + ": OWE supported");
2926             }
2927         }
2928 
2929         if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork
2930                 .KeyMgmtMask.DPP) != 0) {
2931             advancedCapabilities |= WIFI_FEATURE_DPP;
2932 
2933             if (mVerboseLoggingEnabled) {
2934                 Log.v(TAG, methodStr + ": DPP supported");
2935             }
2936             if (isV1_4()) {
2937                 advancedCapabilities |= WIFI_FEATURE_DPP_ENROLLEE_RESPONDER;
2938                 if (mVerboseLoggingEnabled) {
2939                     Log.v(TAG, methodStr + ": DPP ENROLLEE RESPONDER supported");
2940                 }
2941             }
2942         }
2943 
2944         if (isV1_4()) {
2945             advancedCapabilities |= WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS
2946                     | WIFI_FEATURE_DECORATED_IDENTITY;
2947             if (mVerboseLoggingEnabled) {
2948                 Log.v(TAG, methodStr + ": Passpoint T&C supported");
2949                 Log.v(TAG, methodStr + ": RFC 7542 decorated identity supported");
2950             }
2951         }
2952 
2953         if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork
2954                 .KeyMgmtMask.WAPI_PSK) != 0) {
2955             advancedCapabilities |= WIFI_FEATURE_WAPI;
2956 
2957             if (mVerboseLoggingEnabled) {
2958                 Log.v(TAG, methodStr + ": WAPI supported");
2959             }
2960         }
2961 
2962         if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork
2963                 .KeyMgmtMask.FILS_SHA256) != 0) {
2964             advancedCapabilities |= WIFI_FEATURE_FILS_SHA256;
2965 
2966             if (mVerboseLoggingEnabled) {
2967                 Log.v(TAG, methodStr + ": FILS_SHA256 supported");
2968             }
2969         }
2970         if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork
2971                 .KeyMgmtMask.FILS_SHA384) != 0) {
2972             advancedCapabilities |= WIFI_FEATURE_FILS_SHA384;
2973 
2974             if (mVerboseLoggingEnabled) {
2975                 Log.v(TAG, methodStr + ": FILS_SHA384 supported");
2976             }
2977         }
2978 
2979         if (mVerboseLoggingEnabled) {
2980             Log.v(TAG, methodStr + ": Capability flags = " + keyMgmtCapabilities);
2981         }
2982 
2983         return advancedCapabilities;
2984     }
2985 
getKeyMgmtCapabilities_1_3(@onNull String ifaceName)2986     private int getKeyMgmtCapabilities_1_3(@NonNull String ifaceName) {
2987         final String methodStr = "getKeyMgmtCapabilities_1_3";
2988         Mutable<Integer> keyMgmtMask = new Mutable<>(0);
2989         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
2990         if (iface == null) {
2991             return 0;
2992         }
2993 
2994         // Get a v1.3 supplicant STA Interface
2995         android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 =
2996                 getStaIfaceMockableV1_3(iface);
2997         if (staIfaceV13 == null) {
2998             Log.e(TAG, methodStr
2999                     + ": ISupplicantStaIface V1.3 is null, cannot get advanced capabilities");
3000             return 0;
3001         }
3002 
3003         try {
3004             // Support for new key management types; WAPI_PSK, WAPI_CERT
3005             // Requires HAL v1.3 or higher
3006             staIfaceV13.getKeyMgmtCapabilities_1_3(
3007                     (SupplicantStatus statusInternal, int keyMgmtMaskInternal) -> {
3008                         if (statusInternal.code == SupplicantStatusCode.SUCCESS) {
3009                             keyMgmtMask.value = keyMgmtMaskInternal;
3010                         }
3011                         checkStatusAndLogFailure(statusInternal, methodStr);
3012                     });
3013         } catch (RemoteException e) {
3014             handleRemoteException(e, methodStr);
3015         }
3016         return keyMgmtMask.value;
3017     }
3018 
getKeyMgmtCapabilities(@onNull String ifaceName)3019     private int getKeyMgmtCapabilities(@NonNull String ifaceName) {
3020         final String methodStr = "getKeyMgmtCapabilities";
3021         Mutable<Boolean> status = new Mutable<>(false);
3022         Mutable<Integer> keyMgmtMask = new Mutable<>(0);
3023 
3024         if (isV1_3()) {
3025             keyMgmtMask.value = getKeyMgmtCapabilities_1_3(ifaceName);
3026         } else if (isV1_2()) {
3027             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3028             if (iface == null) {
3029                 return 0;
3030             }
3031 
3032             // Get a v1.2 supplicant STA Interface
3033             android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 =
3034                     getStaIfaceMockableV1_2(iface);
3035 
3036             if (staIfaceV12 == null) {
3037                 Log.e(TAG, methodStr
3038                         + ": ISupplicantStaIface is null, cannot get advanced capabilities");
3039                 return 0;
3040             }
3041 
3042             try {
3043                 // Support for new key management types; SAE, SUITE_B, OWE
3044                 // Requires HAL v1.2 or higher
3045                 staIfaceV12.getKeyMgmtCapabilities(
3046                         (SupplicantStatus statusInternal, int keyMgmtMaskInternal) -> {
3047                             status.value = statusInternal.code == SupplicantStatusCode.SUCCESS;
3048                             if (status.value) {
3049                                 keyMgmtMask.value = keyMgmtMaskInternal;
3050                             }
3051                             checkStatusAndLogFailure(statusInternal, methodStr);
3052                         });
3053             } catch (RemoteException e) {
3054                 handleRemoteException(e, methodStr);
3055             }
3056         } else {
3057             Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
3058         }
3059 
3060         // 0 is returned in case of an error
3061         return keyMgmtMask.value;
3062     }
3063 
getWpaDriverCapabilities_1_4(@onNull String ifaceName)3064     private Mutable<Integer> getWpaDriverCapabilities_1_4(@NonNull String ifaceName) {
3065         final String methodStr = "getWpaDriverCapabilities_1_4";
3066         Mutable<Integer> drvCapabilitiesMask = new Mutable<>(0);
3067         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3068 
3069         if (null == iface) return drvCapabilitiesMask;
3070 
3071         android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface staIfaceV14 =
3072                 getStaIfaceMockableV1_4(iface);
3073         if (null == staIfaceV14) {
3074             Log.e(TAG, methodStr
3075                     + ": SupplicantStaIface is null, cannot get wpa driver features");
3076             return drvCapabilitiesMask;
3077         }
3078 
3079         try {
3080             staIfaceV14.getWpaDriverCapabilities_1_4(
3081                     (android.hardware.wifi.supplicant.V1_4.SupplicantStatus statusInternal,
3082                             int drvCapabilities) -> {
3083                         if (statusInternal.code
3084                                 == android.hardware.wifi.supplicant.V1_4
3085                                 .SupplicantStatusCode.SUCCESS) {
3086                             drvCapabilitiesMask.value = drvCapabilities;
3087                         }
3088                         checkStatusAndLogFailure(statusInternal, methodStr);
3089                     });
3090         } catch (RemoteException e) {
3091             handleRemoteException(e, methodStr);
3092         }
3093         return drvCapabilitiesMask;
3094     }
3095 
getWpaDriverCapabilities_1_3(@onNull String ifaceName)3096     private Mutable<Integer> getWpaDriverCapabilities_1_3(@NonNull String ifaceName) {
3097         final String methodStr = "getWpaDriverCapabilities_1_3";
3098         Mutable<Integer> drvCapabilitiesMask = new Mutable<>(0);
3099         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3100 
3101         if (null == iface) return drvCapabilitiesMask;
3102 
3103         android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 =
3104                 getStaIfaceMockableV1_3(iface);
3105         if (null == staIfaceV13) {
3106             Log.e(TAG, methodStr
3107                     + ": SupplicantStaIface is null, cannot get wpa driver features");
3108             return drvCapabilitiesMask;
3109         }
3110 
3111         try {
3112             staIfaceV13.getWpaDriverCapabilities(
3113                     (SupplicantStatus statusInternal, int drvCapabilities) -> {
3114                         if (statusInternal.code == SupplicantStatusCode.SUCCESS) {
3115                             drvCapabilitiesMask.value = drvCapabilities;
3116                         }
3117                         checkStatusAndLogFailure(statusInternal, methodStr);
3118                     });
3119         } catch (RemoteException e) {
3120             handleRemoteException(e, methodStr);
3121         }
3122         return drvCapabilitiesMask;
3123     }
3124 
3125     /**
3126      * Get the driver supported features through supplicant.
3127      *
3128      * @param ifaceName Name of the interface.
3129      * @return bitmask defined by WifiManager.WIFI_FEATURE_*.
3130      */
getWpaDriverFeatureSet(@onNull String ifaceName)3131     public long getWpaDriverFeatureSet(@NonNull String ifaceName) {
3132         final String methodStr = "getWpaDriverFeatureSet";
3133         Mutable<Integer> drvCapabilitiesMask = new Mutable<>(0);
3134         long featureSet = 0;
3135 
3136         if (isV1_4()) {
3137             drvCapabilitiesMask = getWpaDriverCapabilities_1_4(ifaceName);
3138         } else if (isV1_3()) {
3139             drvCapabilitiesMask = getWpaDriverCapabilities_1_3(ifaceName);
3140         } else {
3141             Log.i(TAG, "Method " + methodStr + " is not supported in existing HAL");
3142             return 0;
3143         }
3144 
3145         if ((drvCapabilitiesMask.value & WpaDriverCapabilitiesMask.MBO) != 0) {
3146             featureSet |= WIFI_FEATURE_MBO;
3147             if (mVerboseLoggingEnabled) {
3148                 Log.v(TAG, methodStr + ": MBO supported");
3149             }
3150             if ((drvCapabilitiesMask.value
3151                     & WpaDriverCapabilitiesMask.OCE) != 0) {
3152                 featureSet |= WIFI_FEATURE_OCE;
3153                 if (mVerboseLoggingEnabled) {
3154                     Log.v(TAG, methodStr + ": OCE supported");
3155                 }
3156             }
3157         }
3158 
3159         if ((drvCapabilitiesMask.value
3160                 & android.hardware.wifi.supplicant.V1_4.WpaDriverCapabilitiesMask.SAE_PK) != 0) {
3161             featureSet |= WIFI_FEATURE_SAE_PK;
3162             if (mVerboseLoggingEnabled) {
3163                 Log.v(TAG, methodStr + ": SAE-PK supported");
3164             }
3165         }
3166 
3167         if ((drvCapabilitiesMask.value
3168                 & android.hardware.wifi.supplicant.V1_4.WpaDriverCapabilitiesMask.WFD_R2) != 0) {
3169             featureSet |= WIFI_FEATURE_WFD_R2;
3170             if (mVerboseLoggingEnabled) {
3171                 Log.v(TAG, methodStr + ": WFD-R2 supported");
3172             }
3173         }
3174 
3175         return featureSet;
3176     }
3177 
getWifiStandard(int technology)3178     private @WifiStandard int getWifiStandard(int technology) {
3179         switch(technology) {
3180             case WifiTechnology.HE:
3181                 return ScanResult.WIFI_STANDARD_11AX;
3182             case WifiTechnology.VHT:
3183                 return ScanResult.WIFI_STANDARD_11AC;
3184             case WifiTechnology.HT:
3185                 return ScanResult.WIFI_STANDARD_11N;
3186             case WifiTechnology.LEGACY:
3187                 return ScanResult.WIFI_STANDARD_LEGACY;
3188             default:
3189                 return ScanResult.WIFI_STANDARD_UNKNOWN;
3190         }
3191     }
3192 
getChannelBandwidth(int channelBandwidth)3193     private int getChannelBandwidth(int channelBandwidth) {
3194         switch(channelBandwidth) {
3195             case WifiChannelWidthInMhz.WIDTH_20:
3196                 return ScanResult.CHANNEL_WIDTH_20MHZ;
3197             case WifiChannelWidthInMhz.WIDTH_40:
3198                 return ScanResult.CHANNEL_WIDTH_40MHZ;
3199             case WifiChannelWidthInMhz.WIDTH_80:
3200                 return ScanResult.CHANNEL_WIDTH_80MHZ;
3201             case WifiChannelWidthInMhz.WIDTH_160:
3202                 return ScanResult.CHANNEL_WIDTH_160MHZ;
3203             case WifiChannelWidthInMhz.WIDTH_80P80:
3204                 return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
3205             default:
3206                 return ScanResult.CHANNEL_WIDTH_20MHZ;
3207         }
3208     }
3209 
frameworkToHidlDppAkm(int dppAkm)3210     private int frameworkToHidlDppAkm(int dppAkm) {
3211         switch(dppAkm) {
3212             case SupplicantStaIfaceHal.DppAkm.PSK:
3213                 return DppAkm.PSK;
3214             case SupplicantStaIfaceHal.DppAkm.PSK_SAE:
3215                 return DppAkm.PSK_SAE;
3216             case SupplicantStaIfaceHal.DppAkm.SAE:
3217                 return DppAkm.SAE;
3218             case SupplicantStaIfaceHal.DppAkm.DPP:
3219                 return DppAkm.DPP;
3220             default:
3221                 Log.e(TAG, "Invalid DppAkm received");
3222                 return -1;
3223         }
3224     }
3225 
frameworkToHidlDppCurve(int dppCurve)3226     private int frameworkToHidlDppCurve(int dppCurve) {
3227         switch(dppCurve) {
3228             case SupplicantStaIfaceHal.DppCurve.PRIME256V1:
3229                 return DppCurve.PRIME256V1;
3230             case SupplicantStaIfaceHal.DppCurve.SECP384R1:
3231                 return DppCurve.SECP384R1;
3232             case SupplicantStaIfaceHal.DppCurve.SECP521R1:
3233                 return DppCurve.SECP521R1;
3234             case SupplicantStaIfaceHal.DppCurve.BRAINPOOLP256R1:
3235                 return DppCurve.BRAINPOOLP256R1;
3236             case SupplicantStaIfaceHal.DppCurve.BRAINPOOLP384R1:
3237                 return DppCurve.BRAINPOOLP384R1;
3238             case SupplicantStaIfaceHal.DppCurve.BRAINPOOLP512R1:
3239                 return DppCurve.BRAINPOOLP512R1;
3240             default:
3241                 Log.e(TAG, "Invalid DppAkm received");
3242                 return -1;
3243         }
3244     }
3245 
frameworkToHidlDppNetRole(int dppNetRole)3246     private int frameworkToHidlDppNetRole(int dppNetRole) {
3247         switch(dppNetRole) {
3248             case SupplicantStaIfaceHal.DppNetRole.STA:
3249                 return DppNetRole.STA;
3250             case SupplicantStaIfaceHal.DppNetRole.AP:
3251                 return DppNetRole.AP;
3252             default:
3253                 Log.e(TAG, "Invalid DppNetRole received");
3254                 return -1;
3255         }
3256     }
3257 
3258     /**
3259      * Returns connection capabilities of the current network
3260      *
3261      *  This is a v1.3+ HAL feature.
3262      * @param ifaceName Name of the interface.
3263      * @return connection capabilities of the current network
3264      */
getConnectionCapabilities(@onNull String ifaceName)3265     public WifiNative.ConnectionCapabilities getConnectionCapabilities(@NonNull String ifaceName) {
3266         final String methodStr = "getConnectionCapabilities";
3267         WifiNative.ConnectionCapabilities capOut = new WifiNative.ConnectionCapabilities();
3268         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3269         if (iface == null) {
3270             return capOut;
3271         }
3272         if (isV1_4()) {
3273             return getConnectionCapabilities_1_4(iface);
3274         } else if (isV1_3()) {
3275             return getConnectionCapabilities_1_3(iface);
3276         } else {
3277             Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
3278         }
3279         return capOut;
3280     }
3281 
3282     /**
3283      * Returns connection MLO links info
3284      *
3285      * @param ifaceName Name of the interface.
3286      * @return null since this method is not supported on Hidl
3287      */
getConnectionMloLinksInfo(@onNull String ifaceName)3288     public WifiNative.ConnectionMloLinksInfo getConnectionMloLinksInfo(@NonNull String ifaceName) {
3289         return null;
3290     }
3291 
getConnectionCapabilities_1_3( @onNull ISupplicantStaIface iface)3292     private WifiNative.ConnectionCapabilities getConnectionCapabilities_1_3(
3293             @NonNull ISupplicantStaIface iface) {
3294         final String methodStr = "getConnectionCapabilities_1_3";
3295         WifiNative.ConnectionCapabilities capOut = new WifiNative.ConnectionCapabilities();
3296 
3297         // Get a v1.3 supplicant STA Interface
3298         android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 =
3299                 getStaIfaceMockableV1_3(iface);
3300 
3301         if (staIfaceV13 == null) {
3302             Log.e(TAG, methodStr
3303                     + ": SupplicantStaIface is null, cannot get Connection Capabilities");
3304             return capOut;
3305         }
3306 
3307         try {
3308             staIfaceV13.getConnectionCapabilities(
3309                     (SupplicantStatus statusInternal, ConnectionCapabilities cap) -> {
3310                         if (statusInternal.code == SupplicantStatusCode.SUCCESS) {
3311                             capOut.wifiStandard = getWifiStandard(cap.technology);
3312                             capOut.channelBandwidth = getChannelBandwidth(
3313                                     cap.channelBandwidth);
3314                             capOut.maxNumberTxSpatialStreams = cap.maxNumberTxSpatialStreams;
3315                             capOut.maxNumberRxSpatialStreams = cap.maxNumberRxSpatialStreams;
3316                         }
3317                         checkStatusAndLogFailure(statusInternal, methodStr);
3318                     });
3319         } catch (RemoteException e) {
3320             handleRemoteException(e, methodStr);
3321         }
3322         return capOut;
3323     }
3324 
getConnectionCapabilities_1_4( @onNull ISupplicantStaIface iface)3325     private WifiNative.ConnectionCapabilities getConnectionCapabilities_1_4(
3326             @NonNull ISupplicantStaIface iface) {
3327         final String methodStr = "getConnectionCapabilities_1_4";
3328         WifiNative.ConnectionCapabilities capOut = new WifiNative.ConnectionCapabilities();
3329         // Get a v1.4 supplicant STA Interface
3330         android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface staIfaceV14 =
3331                 getStaIfaceMockableV1_4(iface);
3332 
3333         if (staIfaceV14 == null) {
3334             Log.e(TAG, methodStr
3335                     + ": SupplicantStaIface is null, cannot get Connection Capabilities");
3336             return capOut;
3337         }
3338 
3339         try {
3340             staIfaceV14.getConnectionCapabilities_1_4(
3341                     (android.hardware.wifi.supplicant.V1_4.SupplicantStatus statusInternal,
3342                             android.hardware.wifi.supplicant.V1_4.ConnectionCapabilities cap)
3343                             -> {
3344                         if (statusInternal.code == SupplicantStatusCode.SUCCESS) {
3345                             capOut.wifiStandard = getWifiStandard(cap.V1_3.technology);
3346                             capOut.channelBandwidth = getChannelBandwidth(
3347                                     cap.V1_3.channelBandwidth);
3348                             capOut.is11bMode = (cap.legacyMode == LegacyMode.B_MODE);
3349                             capOut.maxNumberTxSpatialStreams = cap.V1_3.maxNumberTxSpatialStreams;
3350                             capOut.maxNumberRxSpatialStreams = cap.V1_3.maxNumberRxSpatialStreams;
3351                         }
3352                         checkStatusAndLogFailure(statusInternal, methodStr);
3353                     });
3354         } catch (RemoteException e) {
3355             handleRemoteException(e, methodStr);
3356         }
3357         return capOut;
3358     }
3359     /**
3360      * Adds a DPP peer URI to the URI list.
3361      *
3362      *  This is a v1.2+ HAL feature.
3363      *  Returns an ID to be used later to refer to this URI (>0).
3364      *  On error, or if these features are not supported, -1 is returned.
3365      */
addDppPeerUri(@onNull String ifaceName, @NonNull String uri)3366     public int addDppPeerUri(@NonNull String ifaceName, @NonNull String uri) {
3367         final String methodStr = "addDppPeerUri";
3368         Mutable<Boolean> status = new Mutable<>(false);
3369         Mutable<Integer> bootstrapId = new Mutable<>(-1);
3370 
3371         if (!isV1_2()) {
3372             Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
3373             return -1;
3374         }
3375 
3376         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3377         if (iface == null) {
3378             return -1;
3379         }
3380 
3381         // Get a v1.2 supplicant STA Interface
3382         android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 =
3383                 getStaIfaceMockableV1_2(iface);
3384 
3385         if (staIfaceV12 == null) {
3386             Log.e(TAG, methodStr + ": ISupplicantStaIface is null");
3387             return -1;
3388         }
3389 
3390         try {
3391             // Support for DPP (Easy connect)
3392             // Requires HAL v1.2 or higher
3393             staIfaceV12.addDppPeerUri(uri,
3394                     (SupplicantStatus statusInternal, int bootstrapIdInternal) -> {
3395                         status.value = statusInternal.code == SupplicantStatusCode.SUCCESS;
3396                         if (status.value) {
3397                             bootstrapId.value = bootstrapIdInternal;
3398                         }
3399                         checkStatusAndLogFailure(statusInternal, methodStr);
3400                     });
3401         } catch (RemoteException e) {
3402             handleRemoteException(e, methodStr);
3403             return -1;
3404         }
3405 
3406         return bootstrapId.value;
3407     }
3408 
3409     /**
3410      * Removes a DPP URI to the URI list given an ID.
3411      *
3412      *  This is a v1.2+ HAL feature.
3413      *  Returns true when operation is successful
3414      *  On error, or if these features are not supported, false is returned.
3415      */
removeDppUri(@onNull String ifaceName, int bootstrapId)3416     public boolean removeDppUri(@NonNull String ifaceName, int bootstrapId)  {
3417         final String methodStr = "removeDppUri";
3418 
3419         if (!isV1_2()) {
3420             Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
3421             return false;
3422         }
3423 
3424         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3425         if (iface == null) {
3426             return false;
3427         }
3428 
3429         // Get a v1.2 supplicant STA Interface
3430         android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 =
3431                 getStaIfaceMockableV1_2(iface);
3432 
3433         if (staIfaceV12 == null) {
3434             Log.e(TAG, methodStr + ": ISupplicantStaIface is null");
3435             return false;
3436         }
3437 
3438         try {
3439             // Support for DPP (Easy connect)
3440             // Requires HAL v1.2 or higher
3441             SupplicantStatus status = staIfaceV12.removeDppUri(bootstrapId);
3442             return checkStatusAndLogFailure(status, methodStr);
3443         } catch (RemoteException e) {
3444             handleRemoteException(e, methodStr);
3445         }
3446 
3447         return false;
3448     }
3449 
3450     /**
3451      * Stops/aborts DPP Initiator request
3452      *
3453      *  This is a v1.2+ HAL feature.
3454      *  Returns true when operation is successful
3455      *  On error, or if these features are not supported, false is returned.
3456      */
stopDppInitiator(@onNull String ifaceName)3457     public boolean stopDppInitiator(@NonNull String ifaceName)  {
3458         final String methodStr = "stopDppInitiator";
3459 
3460         if (!isV1_2()) {
3461             return false;
3462         }
3463 
3464         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3465         if (iface == null) {
3466             return false;
3467         }
3468 
3469         // Get a v1.2 supplicant STA Interface
3470         android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 =
3471                 getStaIfaceMockableV1_2(iface);
3472 
3473         if (staIfaceV12 == null) {
3474             Log.e(TAG, methodStr + ": ISupplicantStaIface is null");
3475             return false;
3476         }
3477 
3478         try {
3479             // Support for DPP (Easy connect)
3480             // Requires HAL v1.2 or higher
3481             SupplicantStatus status = staIfaceV12.stopDppInitiator();
3482             return checkStatusAndLogFailure(status, methodStr);
3483         } catch (RemoteException e) {
3484             handleRemoteException(e, methodStr);
3485         }
3486 
3487         return false;
3488     }
3489 
3490     /**
3491      * Starts DPP Configurator-Initiator request
3492      *
3493      *  This is a v1.2+ HAL feature.
3494      *  Returns true when operation is successful
3495      *  On error, or if these features are not supported, false is returned.
3496      */
startDppConfiguratorInitiator(@onNull String ifaceName, int peerBootstrapId, int ownBootstrapId, @NonNull String ssid, String password, String psk, int netRole, int securityAkm, byte[] privEckey)3497     public boolean startDppConfiguratorInitiator(@NonNull String ifaceName, int peerBootstrapId,
3498             int ownBootstrapId, @NonNull String ssid, String password, String psk,
3499             int netRole, int securityAkm, byte[] privEckey)  {
3500         final String methodStr = "startDppConfiguratorInitiator";
3501 
3502         if (!isV1_2()) {
3503             Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
3504             return false;
3505         }
3506 
3507         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3508         if (iface == null) {
3509             return false;
3510         }
3511 
3512         // Get a v1.2 supplicant STA Interface
3513         android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 =
3514                 getStaIfaceMockableV1_2(iface);
3515 
3516         if (staIfaceV12 == null) {
3517             Log.e(TAG, methodStr + ": ISupplicantStaIface is null");
3518             return false;
3519         }
3520 
3521         try {
3522             // Support for DPP (Easy connect)
3523             // Requires HAL v1.2 or higher
3524             SupplicantStatus status = staIfaceV12.startDppConfiguratorInitiator(peerBootstrapId,
3525                     ownBootstrapId, ssid, password != null ? password : "", psk != null ? psk : "",
3526                     frameworkToHidlDppNetRole(netRole), frameworkToHidlDppAkm(securityAkm));
3527             return checkStatusAndLogFailure(status, methodStr);
3528         } catch (RemoteException e) {
3529             handleRemoteException(e, methodStr);
3530         }
3531 
3532         return false;
3533     }
3534 
3535     /**
3536      * Starts DPP Enrollee-Initiator request
3537      *
3538      *  This is a v1.2+ HAL feature.
3539      *  Returns true when operation is successful
3540      *  On error, or if these features are not supported, false is returned.
3541      */
startDppEnrolleeInitiator(@onNull String ifaceName, int peerBootstrapId, int ownBootstrapId)3542     public boolean startDppEnrolleeInitiator(@NonNull String ifaceName, int peerBootstrapId,
3543             int ownBootstrapId)  {
3544         final String methodStr = "startDppEnrolleeInitiator";
3545 
3546         if (!isV1_2()) {
3547             Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
3548             return false;
3549         }
3550 
3551         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3552         if (iface == null) {
3553             return false;
3554         }
3555 
3556         // Get a v1.2 supplicant STA Interface
3557         android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface staIfaceV12 =
3558                 getStaIfaceMockableV1_2(iface);
3559 
3560         if (staIfaceV12 == null) {
3561             Log.e(TAG, methodStr + ": ISupplicantStaIface is null");
3562             return false;
3563         }
3564 
3565         try {
3566             // Support for DPP (Easy connect)
3567             // Requires HAL v1.2 or higher
3568             SupplicantStatus status = staIfaceV12.startDppEnrolleeInitiator(peerBootstrapId,
3569                     ownBootstrapId);
3570             return checkStatusAndLogFailure(status, methodStr);
3571         } catch (RemoteException e) {
3572             handleRemoteException(e, methodStr);
3573         }
3574 
3575         return false;
3576     }
3577 
3578     /**
3579      * Generate a DPP QR code based boot strap info
3580      *
3581      *  This is a v1.4+ HAL feature.
3582      *  Returns DppResponderBootstrapInfo;
3583      */
generateDppBootstrapInfoForResponder( @onNull String ifaceName, String macAddress, @NonNull String deviceInfo, int dppCurve)3584     public WifiNative.DppBootstrapQrCodeInfo generateDppBootstrapInfoForResponder(
3585             @NonNull String ifaceName, String macAddress, @NonNull String deviceInfo,
3586             int dppCurve) {
3587         final String methodStr = "generateDppBootstrapInfoForResponder";
3588         Mutable<Boolean> status = new Mutable<>(false);
3589         WifiNative.DppBootstrapQrCodeInfo bootstrapInfoOut =
3590                 new WifiNative.DppBootstrapQrCodeInfo();
3591 
3592         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3593         if (iface == null) {
3594             return bootstrapInfoOut;
3595         }
3596 
3597         // Get a v1.4 supplicant STA Interface
3598         android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface staIfaceV14 =
3599                 getStaIfaceMockableV1_4(iface);
3600 
3601         if (staIfaceV14 == null) {
3602             Log.e(TAG, methodStr + ": SupplicantStaIface V1.4 is null");
3603             return bootstrapInfoOut;
3604         }
3605 
3606         try {
3607             // Support for DPP Responder
3608             // Requires HAL v1.4 or higher
3609             staIfaceV14.generateDppBootstrapInfoForResponder(
3610                     NativeUtil.macAddressToByteArray(macAddress), deviceInfo,
3611                     frameworkToHidlDppCurve(dppCurve),
3612                     (android.hardware.wifi.supplicant.V1_4.SupplicantStatus statusInternal,
3613                             android.hardware.wifi.supplicant.V1_4
3614                                     .DppResponderBootstrapInfo info) -> {
3615                         if (statusInternal.code == SupplicantStatusCode.SUCCESS) {
3616                             bootstrapInfoOut.bootstrapId = info.bootstrapId;
3617                             bootstrapInfoOut.listenChannel = info.listenChannel;
3618                             bootstrapInfoOut.uri = info.uri;
3619                         }
3620                         checkStatusAndLogFailure(statusInternal, methodStr);
3621                     });
3622         } catch (RemoteException e) {
3623             handleRemoteException(e, methodStr);
3624             return bootstrapInfoOut;
3625         }
3626 
3627         return bootstrapInfoOut;
3628     }
3629 
3630     /**
3631      * Starts DPP Enrollee-Responder request
3632      *
3633      *  This is a v1.4+ HAL feature.
3634      *  Returns true when operation is successful
3635      *  On error, or if these features are not supported, false is returned.
3636      */
startDppEnrolleeResponder(@onNull String ifaceName, int listenChannel)3637     public boolean startDppEnrolleeResponder(@NonNull String ifaceName, int listenChannel) {
3638         final String methodStr = "startDppEnrolleeResponder";
3639 
3640         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3641         if (iface == null) {
3642             return false;
3643         }
3644 
3645         // Get a v1.4 supplicant STA Interface
3646         android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface staIfaceV14 =
3647                 getStaIfaceMockableV1_4(iface);
3648 
3649         if (staIfaceV14 == null) {
3650             Log.e(TAG, methodStr + ": ISupplicantStaIface V1.4 is null");
3651             return false;
3652         }
3653 
3654         try {
3655             // Support for DPP Responder
3656             // Requires HAL v1.4 or higher
3657             android.hardware.wifi.supplicant.V1_4.SupplicantStatus status =
3658                     staIfaceV14.startDppEnrolleeResponder(listenChannel);
3659             return checkStatusAndLogFailure(status, methodStr);
3660         } catch (RemoteException e) {
3661             handleRemoteException(e, methodStr);
3662         }
3663 
3664         return false;
3665     }
3666 
3667     /**
3668      * Stops/aborts DPP Responder request.
3669      *
3670      *  This is a v1.4+ HAL feature.
3671      *  Returns true when operation is successful
3672      *  On error, or if these features are not supported, false is returned.
3673      */
stopDppResponder(@onNull String ifaceName, int ownBootstrapId)3674     public boolean stopDppResponder(@NonNull String ifaceName, int ownBootstrapId)  {
3675         final String methodStr = "stopDppResponder";
3676 
3677         ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3678         if (iface == null) {
3679             return false;
3680         }
3681 
3682         // Get a v1.4 supplicant STA Interface
3683         android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface staIfaceV14 =
3684                 getStaIfaceMockableV1_4(iface);
3685 
3686         if (staIfaceV14 == null) {
3687             Log.e(TAG, methodStr + ": ISupplicantStaIface V1.4 is null");
3688             return false;
3689         }
3690 
3691         try {
3692             // Support for DPP Responder
3693             // Requires HAL v1.4 or higher
3694             android.hardware.wifi.supplicant.V1_4.SupplicantStatus status =
3695                     staIfaceV14.stopDppResponder(ownBootstrapId);
3696             return checkStatusAndLogFailure(status, methodStr);
3697         } catch (RemoteException e) {
3698             handleRemoteException(e, methodStr);
3699         }
3700 
3701         return false;
3702     }
3703 
3704 
3705     /**
3706      * Register callbacks for DPP events.
3707      *
3708      * @param dppCallback DPP callback object.
3709      */
registerDppCallback(DppEventCallback dppCallback)3710     public void registerDppCallback(DppEventCallback dppCallback) {
3711         mDppCallback = dppCallback;
3712     }
3713 
getDppCallback()3714     protected DppEventCallback getDppCallback() {
3715         return mDppCallback;
3716     }
3717 
3718     /**
3719      * Set MBO cellular data availability.
3720      *
3721      * @param ifaceName Name of the interface.
3722      * @param available true means cellular data available, false otherwise.
3723      * @return None.
3724      */
setMboCellularDataStatus(@onNull String ifaceName, boolean available)3725     public boolean setMboCellularDataStatus(@NonNull String ifaceName, boolean available) {
3726         final String methodStr = "setMboCellularDataStatus";
3727 
3728         if (isV1_3()) {
3729             ISupplicantStaIface iface = checkSupplicantStaIfaceAndLogFailure(ifaceName, methodStr);
3730             if (iface == null) {
3731                 return false;
3732             }
3733 
3734             // Get a v1.3 supplicant STA Interface
3735             android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface staIfaceV13 =
3736                     getStaIfaceMockableV1_3(iface);
3737             if (staIfaceV13 == null) {
3738                 Log.e(TAG, methodStr
3739                         + ": SupplicantStaIface is null, cannot update cell status");
3740                 return false;
3741             }
3742 
3743             try {
3744                 SupplicantStatus status = staIfaceV13.setMboCellularDataStatus(available);
3745                 return checkStatusAndLogFailure(status, methodStr);
3746             } catch (RemoteException e) {
3747                 handleRemoteException(e, methodStr);
3748             }
3749         } else {
3750             Log.e(TAG, "Method " + methodStr + " is not supported in existing HAL");
3751             return false;
3752         }
3753 
3754         return false;
3755     }
3756 
3757     /**
3758      * Check if we've roamed to a linked network and make the linked network the current network
3759      * if we have.
3760      *
3761      * @param ifaceName Name of the interface.
3762      * @param newNetworkId Network id of the new network we've roamed to. If fromFramework is
3763      *                     {@code true}, this will be a framework network id. Otherwise, this will
3764      *                     be a remote network id.
3765      * @param fromFramework {@code true} if the network id is a framework network id, {@code false}
3766                             if the network id is a remote network id.
3767      * @return true if we've roamed to a linked network, false if not.
3768      */
updateOnLinkedNetworkRoaming( @onNull String ifaceName, int newNetworkId, boolean fromFramework)3769     public boolean updateOnLinkedNetworkRoaming(
3770             @NonNull String ifaceName, int newNetworkId, boolean fromFramework) {
3771         synchronized (mLock) {
3772             List<Pair<SupplicantStaNetworkHalHidlImpl, WifiConfiguration>> linkedNetworkHandles =
3773                     mLinkedNetworkLocalAndRemoteConfigs.get(ifaceName);
3774             SupplicantStaNetworkHalHidlImpl currentHandle =
3775                     getCurrentNetworkRemoteHandle(ifaceName);
3776             WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
3777             if (linkedNetworkHandles == null || currentHandle == null || currentConfig == null) {
3778                 return false;
3779             }
3780             if (fromFramework ? currentConfig.networkId == newNetworkId
3781                     : currentHandle.getNetworkId() == newNetworkId) {
3782                 return false;
3783             }
3784             for (Pair<SupplicantStaNetworkHalHidlImpl, WifiConfiguration> pair
3785                     : linkedNetworkHandles) {
3786                 if (fromFramework ? pair.second.networkId == newNetworkId
3787                         : pair.first.getNetworkId() == newNetworkId) {
3788                     Log.i(TAG, "Roamed to linked network, "
3789                             + "make linked network as current network");
3790                     mCurrentNetworkRemoteHandles.put(ifaceName, pair.first);
3791                     mCurrentNetworkLocalConfigs.put(ifaceName, pair.second);
3792                     return true;
3793                 }
3794             }
3795             return false;
3796         }
3797     }
3798 
3799     /**
3800      * Updates the linked networks for the current network and sends them to the supplicant.
3801      *
3802      * @param ifaceName Name of the interface.
3803      * @param networkId network id of the network to link the configurations to.
3804      * @param linkedConfigurations Map of config profile key to config for linking.
3805      * @return true if networks were successfully linked, false otherwise.
3806      */
updateLinkedNetworks(@onNull String ifaceName, int networkId, Map<String, WifiConfiguration> linkedConfigurations)3807     public boolean updateLinkedNetworks(@NonNull String ifaceName, int networkId,
3808             Map<String, WifiConfiguration> linkedConfigurations) {
3809         synchronized (mLock) {
3810             WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
3811             SupplicantStaNetworkHalHidlImpl currentHandle =
3812                     getCurrentNetworkRemoteHandle(ifaceName);
3813 
3814             if (currentConfig == null || currentHandle == null) {
3815                 Log.e(TAG, "current network not configured yet.");
3816                 return false;
3817             }
3818 
3819             if (networkId != currentConfig.networkId) {
3820                 Log.e(TAG, "current config network id is not matching");
3821                 return false;
3822             }
3823 
3824             final int remoteNetworkId = currentHandle.getNetworkId();
3825             if (remoteNetworkId == -1) {
3826                 Log.e(TAG, "current handle getNetworkId failed");
3827                 return false;
3828             }
3829 
3830             if (!removeAllNetworksExcept(ifaceName, remoteNetworkId)) {
3831                 Log.e(TAG, "couldn't remove non-current supplicant networks");
3832                 return false;
3833             }
3834 
3835             mLinkedNetworkLocalAndRemoteConfigs.remove(ifaceName);
3836 
3837             if (linkedConfigurations == null || linkedConfigurations.size() == 0) {
3838                 Log.i(TAG, "cleared linked networks");
3839                 return true;
3840             }
3841 
3842             List<Pair<SupplicantStaNetworkHalHidlImpl, WifiConfiguration>> linkedNetworkHandles =
3843                     new ArrayList<>();
3844             linkedNetworkHandles.add(new Pair(currentHandle, currentConfig));
3845             for (String linkedNetwork : linkedConfigurations.keySet()) {
3846                 Log.i(TAG, "add linked network: " + linkedNetwork);
3847                 Pair<SupplicantStaNetworkHalHidlImpl, WifiConfiguration> pair =
3848                         addNetworkAndSaveConfig(ifaceName, linkedConfigurations.get(linkedNetwork));
3849                 if (pair == null) {
3850                     Log.e(TAG, "failed to add/save linked network: " + linkedNetwork);
3851                     return false;
3852                 }
3853                 pair.first.enable(true);
3854                 linkedNetworkHandles.add(pair);
3855             }
3856 
3857             mLinkedNetworkLocalAndRemoteConfigs.put(ifaceName, linkedNetworkHandles);
3858 
3859             return true;
3860         }
3861     }
3862 
3863     /**
3864      * Remove all networks except the supplied network ID from supplicant
3865      *
3866      * @param ifaceName Name of the interface
3867      * @param networkId network id to keep
3868      */
removeAllNetworksExcept(@onNull String ifaceName, int networkId)3869     private boolean removeAllNetworksExcept(@NonNull String ifaceName, int networkId) {
3870         synchronized (mLock) {
3871             List<Integer> networks = listNetworks(ifaceName);
3872             if (networks == null) {
3873                 Log.e(TAG, "removeAllNetworksExcept failed, got null networks");
3874                 return false;
3875             }
3876             for (int id : networks) {
3877                 if (networkId == id) {
3878                     continue;
3879                 }
3880                 if (!removeNetwork(ifaceName, id)) {
3881                     Log.e(TAG, "removeAllNetworksExcept failed to remove network: " + id);
3882                     return false;
3883                 }
3884             }
3885             return true;
3886         }
3887     }
3888 
3889     /**
3890      * Gets the security params of the current network associated with this interface
3891      *
3892      * @param ifaceName Name of the interface
3893      * @return Security params of the current network associated with the interface
3894      */
getCurrentNetworkSecurityParams(@onNull String ifaceName)3895     public SecurityParams getCurrentNetworkSecurityParams(@NonNull String ifaceName) {
3896         WifiConfiguration currentConfig = getCurrentNetworkLocalConfig(ifaceName);
3897 
3898         if (currentConfig == null) {
3899             return null;
3900         }
3901 
3902         return currentConfig.getNetworkSelectionStatus().getCandidateSecurityParams();
3903     }
3904 
3905     /**
3906      * Set whether the network-centric QoS policy feature is enabled or not for this interface.
3907      *
3908      * @param ifaceName name of the interface.
3909      * @param isEnabled true if feature is enabled, false otherwise.
3910      * @return true without action since this is not a supported feature.
3911      */
setNetworkCentricQosPolicyFeatureEnabled(@onNull String ifaceName, boolean isEnabled)3912     public boolean setNetworkCentricQosPolicyFeatureEnabled(@NonNull String ifaceName,
3913             boolean isEnabled) {
3914         return false;
3915     }
3916 
3917     /**
3918      * Sends a QoS policy response.
3919      *
3920      * @param ifaceName Name of the interface.
3921      * @param qosPolicyRequestId Dialog token to identify the request.
3922      * @param morePolicies Flag to indicate more QoS policies can be accommodated.
3923      * @param qosPolicyStatusList List of framework QosPolicyStatus objects.
3924      * @return true if response is sent successfully, false otherwise.
3925      */
sendQosPolicyResponse(String ifaceName, int qosPolicyRequestId, boolean morePolicies, @NonNull List<SupplicantStaIfaceHal.QosPolicyStatus> qosPolicyStatusList)3926     public boolean sendQosPolicyResponse(String ifaceName, int qosPolicyRequestId,
3927             boolean morePolicies,
3928             @NonNull List<SupplicantStaIfaceHal.QosPolicyStatus> qosPolicyStatusList) {
3929         Log.e(TAG, "sendQosPolicyResponse is not supported by the HIDL HAL");
3930         return false;
3931     }
3932 
3933     /**
3934      * Indicates the removal of all active QoS policies configured by the AP.
3935      *
3936      * @param ifaceName Name of the interface.
3937      */
removeAllQosPolicies(String ifaceName)3938     public boolean removeAllQosPolicies(String ifaceName) {
3939         Log.e(TAG, "removeAllQosPolicies is not supported by the HIDL HAL");
3940         return false;
3941     }
3942 
3943     /**
3944      * Generate DPP credential for network access
3945      *
3946      * @param ifaceName Name of the interface.
3947      * @param ssid ssid of the network
3948      * @param privEcKey Private EC Key for DPP Configurator
3949      * Returns false. Not Supported throuh HIDL
3950      */
generateSelfDppConfiguration(@onNull String ifaceName, @NonNull String ssid, byte[] privEcKey)3951     public boolean generateSelfDppConfiguration(@NonNull String ifaceName, @NonNull String ssid,
3952             byte[] privEcKey) {
3953         Log.d(TAG, "generateSelfDppConfiguration is not supported");
3954         return false;
3955     }
3956 
3957     /**
3958      * Set the currently configured network's anonymous identity.
3959      *
3960      * @param ifaceName Name of the interface.
3961      * @param anonymousIdentity the anonymouns identity.
3962      * @return true if succeeds, false otherwise.
3963      */
setEapAnonymousIdentity(@onNull String ifaceName, String anonymousIdentity)3964     public boolean setEapAnonymousIdentity(@NonNull String ifaceName, String anonymousIdentity) {
3965         synchronized (mLock) {
3966             SupplicantStaNetworkHalHidlImpl networkHandle =
3967                     checkSupplicantStaNetworkAndLogFailure(ifaceName, "setEapAnonymousIdentity");
3968             if (networkHandle == null) return false;
3969             try {
3970                 return networkHandle.setEapAnonymousIdentity(
3971                         NativeUtil.stringToByteArrayList(anonymousIdentity));
3972             } catch (IllegalArgumentException ex) {
3973                 return false;
3974             }
3975         }
3976     }
3977 }
3978