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