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