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