1 /* 2 * Copyright (C) 2019 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 android.net.wifi; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.IntDef; 21 import android.annotation.IntRange; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.SystemApi; 25 import android.app.compat.CompatChanges; 26 import android.compat.annotation.ChangeId; 27 import android.compat.annotation.EnabledAfter; 28 import android.net.MacAddress; 29 import android.net.wifi.util.Environment; 30 import android.net.wifi.util.HexEncoding; 31 import android.os.Build; 32 import android.os.Parcel; 33 import android.os.Parcelable; 34 import android.text.TextUtils; 35 import android.util.Log; 36 import android.util.SparseIntArray; 37 38 import androidx.annotation.Keep; 39 import androidx.annotation.RequiresApi; 40 import androidx.annotation.VisibleForTesting; 41 42 import com.android.internal.util.Preconditions; 43 import com.android.modules.utils.build.SdkLevel; 44 import com.android.wifi.flags.Flags; 45 46 import java.lang.annotation.Retention; 47 import java.lang.annotation.RetentionPolicy; 48 import java.nio.charset.StandardCharsets; 49 import java.util.ArrayList; 50 import java.util.HashSet; 51 import java.util.List; 52 import java.util.Objects; 53 import java.util.Set; 54 import java.util.stream.Collectors; 55 import java.util.stream.IntStream; 56 57 /** 58 * Configuration for a soft access point (a.k.a. Soft AP, SAP, Hotspot). 59 * 60 * <p>This is input for the framework provided by a client app, i.e. it exposes knobs to instruct 61 * the framework how it should configure a hotspot. 62 * 63 * <p>System apps can use this to configure a tethered hotspot or local-only hotspot. 64 * 65 * <p>Instances of this class are immutable. 66 */ 67 public final class SoftApConfiguration implements Parcelable { 68 69 private static final String TAG = "SoftApConfiguration"; 70 71 @VisibleForTesting 72 static final int PSK_MIN_LEN = 8; 73 74 @VisibleForTesting 75 static final int PSK_MAX_LEN = 63; 76 77 /** 78 * 2GHz band. 79 */ 80 @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS) 81 public static final int BAND_2GHZ = 1 << 0; 82 83 /** 84 * 5GHz band. 85 */ 86 @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS) 87 public static final int BAND_5GHZ = 1 << 1; 88 89 /** 90 * 6GHz band. 91 */ 92 @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS) 93 public static final int BAND_6GHZ = 1 << 2; 94 95 /** 96 * 60GHz band. 97 */ 98 @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS) 99 public static final int BAND_60GHZ = 1 << 3; 100 101 /** 102 * Device is allowed to choose the optimal band (2GHz, 5GHz, 6GHz) based on device capability, 103 * operating country code and current radio conditions. 104 * @hide 105 * 106 * @deprecated This is no longer supported. The value is fixed at 107 * (BAND_2GHZ | BAND_5GHZ | BAND_6GHZ) even if a new band is supported in the future, for 108 * instance {@code BAND_60GHZ}. The bands are a bit mask - use any combination of 109 * {@code BAND_}, for instance {@code BAND_2GHZ | BAND_5GHZ}. 110 */ 111 @SystemApi 112 public static final int BAND_ANY = BAND_2GHZ | BAND_5GHZ | BAND_6GHZ; 113 114 /** 115 * A default value used to configure shut down timeout setting to default value. 116 * See {@link Builder#setShutdownTimeoutMillis(long)} or 117 * {@link Builder#setBridgedModeOpportunisticShutdownTimeoutMillis(long)} for details. 118 * 119 * @hide 120 */ 121 @SystemApi 122 public static final long DEFAULT_TIMEOUT = -1; 123 124 /** @hide */ 125 @Retention(RetentionPolicy.SOURCE) 126 @IntDef(flag = true, prefix = { "BAND_TYPE_" }, value = { 127 BAND_2GHZ, 128 BAND_5GHZ, 129 BAND_6GHZ, 130 BAND_60GHZ, 131 }) 132 public @interface BandType {} 133 134 /** 135 * All of the supported band types. 136 * @hide 137 */ 138 public static int[] BAND_TYPES = {BAND_2GHZ, BAND_5GHZ, BAND_6GHZ, BAND_60GHZ}; 139 isBandValid(@andType int band)140 private static boolean isBandValid(@BandType int band) { 141 int bandAny = BAND_2GHZ | BAND_5GHZ | BAND_6GHZ | BAND_60GHZ; 142 return ((band != 0) && ((band & ~bandAny) == 0)); 143 } 144 145 private static final int MIN_CH_2G_BAND = 1; 146 private static final int MAX_CH_2G_BAND = 14; 147 private static final int MIN_CH_5G_BAND = 34; 148 private static final int MAX_CH_5G_BAND = 196; 149 private static final int MIN_CH_6G_BAND = 1; 150 private static final int MAX_CH_6G_BAND = 253; 151 private static final int MIN_CH_60G_BAND = 1; 152 private static final int MAX_CH_60G_BAND = 6; 153 154 /** 155 * Requires to configure MAC randomization setting to None when configuring BSSID. 156 */ 157 @ChangeId 158 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S) 159 private static final long FORCE_MUTUAL_EXCLUSIVE_BSSID_MAC_RAMDONIZATION_SETTING = 215656264L; 160 161 /** 162 * Removes zero support on 163 * {@link android.net.wifi.SoftApConfiguration.Builder#setShutdownTimeoutMillis(long)}. 164 * 165 * @hide 166 */ 167 @ChangeId 168 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S) 169 public static final long REMOVE_ZERO_FOR_TIMEOUT_SETTING = 213289672L; 170 isChannelBandPairValid(int channel, @BandType int band)171 private static boolean isChannelBandPairValid(int channel, @BandType int band) { 172 switch (band) { 173 case BAND_2GHZ: 174 if (channel < MIN_CH_2G_BAND || channel > MAX_CH_2G_BAND) { 175 return false; 176 } 177 break; 178 179 case BAND_5GHZ: 180 if (channel < MIN_CH_5G_BAND || channel > MAX_CH_5G_BAND) { 181 return false; 182 } 183 break; 184 185 case BAND_6GHZ: 186 if (channel < MIN_CH_6G_BAND || channel > MAX_CH_6G_BAND) { 187 return false; 188 } 189 break; 190 191 case BAND_60GHZ: 192 if (channel < MIN_CH_60G_BAND || channel > MAX_CH_60G_BAND) { 193 return false; 194 } 195 break; 196 197 default: 198 return false; 199 } 200 return true; 201 } 202 203 /** 204 * SSID for the AP, or null for a framework-determined SSID. 205 */ 206 private final @Nullable WifiSsid mWifiSsid; 207 208 /** 209 * BSSID for the AP, or null to use a framework-determined BSSID. 210 */ 211 private final @Nullable MacAddress mBssid; 212 213 /** 214 * Vendor elements for the AP, structured as dd+len+elements 215 */ 216 private final @NonNull List<ScanResult.InformationElement> mVendorElements; 217 218 /** 219 * Pre-shared key for WPA2-PSK or WPA3-SAE-Transition or WPA3-SAE encryption which depends on 220 * the security type. 221 */ 222 private final @Nullable String mPassphrase; 223 224 /** 225 * This is a network that does not broadcast its SSID, so an 226 * SSID-specific probe request must be used for scans. 227 */ 228 private final boolean mHiddenSsid; 229 230 /** 231 * The operating channels of the dual APs. 232 * 233 * The SparseIntArray that consists the band and the channel of matching the band. 234 */ 235 @NonNull 236 private final SparseIntArray mChannels; 237 238 /** 239 * The set of allowed channels in 2.4GHz band to select from using ACS (Automatic Channel 240 * Selection) algorithm. 241 * 242 * Requires the driver to support {@link SoftApCapability#SOFTAP_FEATURE_ACS_OFFLOAD}. 243 * Otherwise, this set will be ignored. 244 * 245 * If the set is empty, then all channels in 2.4GHz band are allowed. 246 */ 247 private final @NonNull Set<Integer> mAllowedAcsChannels2g; 248 249 /** 250 * The set of allowed channels in 5GHz band to select from using ACS (Automatic Channel 251 * Selection) algorithm. 252 * 253 * Requires the driver to support {@link SoftApCapability#SOFTAP_FEATURE_ACS_OFFLOAD}. 254 * Otherwise, this set will be ignored. 255 * 256 * If the set is empty, then all channels in 5GHz are allowed. 257 */ 258 private final @NonNull Set<Integer> mAllowedAcsChannels5g; 259 260 /** 261 * The set of allowed channels in 6GHz band to select from using ACS (Automatic Channel 262 * Selection) algorithm. 263 * 264 * Requires the driver to support {@link SoftApCapability#SOFTAP_FEATURE_ACS_OFFLOAD}. 265 * Otherwise, this set will be ignored. 266 * 267 * If the set is empty, then all channels in 6GHz are allowed. 268 */ 269 private final @NonNull Set<Integer> mAllowedAcsChannels6g; 270 271 /** 272 * The maximum channel bandwidth for SoftAp operation 273 * 274 * Default value is SoftApInfo#CHANNEL_WIDTH_AUTO which means the channel bandwidth 275 * is to be selected by the chip based on device capabilities. 276 * <p> 277 * 278 * Valid values: {@link SoftApInfo#CHANNEL_WIDTH_AUTO}, 279 * {@link SoftApInfo#CHANNEL_WIDTH_20MHZ}, {@link SoftApInfo#CHANNEL_WIDTH_40MHZ}, 280 * {@link SoftApInfo#CHANNEL_WIDTH_80MHZ}, {@link SoftApInfo#CHANNEL_WIDTH_160MHZ}, 281 * {@link SoftApInfo#CHANNEL_WIDTH_320MHZ} 282 * 283 */ 284 private final @WifiAnnotations.Bandwidth int mMaxChannelBandwidth; 285 286 /** 287 * The maximim allowed number of clients that can associate to the AP. 288 */ 289 private final int mMaxNumberOfClients; 290 291 /** 292 * The operating security type of the AP. 293 * One of the following security types: 294 * {@link #SECURITY_TYPE_OPEN}, 295 * {@link #SECURITY_TYPE_WPA2_PSK}, 296 * {@link #SECURITY_TYPE_WPA3_SAE_TRANSITION}, 297 * {@link #SECURITY_TYPE_WPA3_SAE}, 298 * {@link #SECURITY_TYPE_WPA3_OWE_TRANSITION}, 299 * {@link #SECURITY_TYPE_WPA3_OWE} 300 */ 301 private final @SecurityType int mSecurityType; 302 303 /** 304 * The flag to indicate client need to authorize by user 305 * when client is connecting to AP. 306 */ 307 private final boolean mClientControlByUser; 308 309 /** 310 * The list of blocked client that can't associate to the AP. 311 */ 312 private final List<MacAddress> mBlockedClientList; 313 314 /** 315 * The list of allowed client that can associate to the AP. 316 */ 317 private final List<MacAddress> mAllowedClientList; 318 319 /** 320 * Whether auto shutdown of soft AP is enabled or not. 321 */ 322 private final boolean mAutoShutdownEnabled; 323 324 /** 325 * Delay in milliseconds before shutting down soft AP when 326 * there are no connected devices. 327 */ 328 private final long mShutdownTimeoutMillis; 329 330 /** @hide */ 331 @Retention(RetentionPolicy.SOURCE) 332 @IntDef(prefix = {"RANDOMIZATION_"}, value = { 333 RANDOMIZATION_NONE, 334 RANDOMIZATION_PERSISTENT, 335 RANDOMIZATION_NON_PERSISTENT}) 336 public @interface MacRandomizationSetting {} 337 338 /** 339 * Use the factory MAC address as the BSSID of the AP. 340 * 341 * @hide 342 */ 343 @SystemApi 344 public static final int RANDOMIZATION_NONE = 0; 345 346 /** 347 * Generate a persistent randomized MAC address as the BSSID of the AP. 348 * The MAC address is persisted per SSID - i.e. as long as the SSID of the AP doesn't change 349 * then it will have a persistent MAC address (which is initially random and is not the factory 350 * MAC address). 351 * 352 * @hide 353 */ 354 @SystemApi 355 public static final int RANDOMIZATION_PERSISTENT = 1; 356 357 /** 358 * Generate a randomized MAC address as the BSSID of the AP. The MAC address is not persisted 359 * - it is re-generated every time the AP is re-enabled. 360 * @hide 361 */ 362 @SystemApi 363 public static final int RANDOMIZATION_NON_PERSISTENT = 2; 364 365 /** 366 * Level of MAC randomization for the AP BSSID. 367 */ 368 @MacRandomizationSetting 369 private int mMacRandomizationSetting; 370 371 372 /** 373 * Whether opportunistic shutdown of an instance in bridged AP is enabled or not. 374 */ 375 private boolean mBridgedModeOpportunisticShutdownEnabled; 376 377 /** 378 * Whether 802.11ax AP is enabled or not. 379 */ 380 private boolean mIeee80211axEnabled; 381 382 /** 383 * Whether 802.11be AP is enabled or not. 384 */ 385 private boolean mIeee80211beEnabled; 386 387 /** 388 * Whether the current configuration is configured by user or not. 389 */ 390 private boolean mIsUserConfiguration; 391 392 /** 393 * Randomized MAC address to use with this configuration when MAC randomization setting 394 * is {@link #RANDOMIZATION_PERSISTENT}. 395 */ 396 private final @Nullable MacAddress mPersistentRandomizedMacAddress; 397 398 /** 399 * Delay in milliseconds before shutting down an instance in bridged AP. 400 */ 401 private final long mBridgedModeOpportunisticShutdownTimeoutMillis; 402 403 /** List of {@link OuiKeyedData} providing vendor-specific configuration data. */ 404 private @NonNull List<OuiKeyedData> mVendorData; 405 406 /** 407 * Whether connected clients can communicate with each other or not. 408 */ 409 private boolean mIsClientIsolationEnabled; 410 411 /** 412 * THe definition of security type OPEN. 413 */ 414 public static final int SECURITY_TYPE_OPEN = 0; 415 416 /** 417 * The definition of security type WPA2-PSK. 418 */ 419 public static final int SECURITY_TYPE_WPA2_PSK = 1; 420 421 /** 422 * The definition of security type WPA3-SAE Transition mode. 423 */ 424 public static final int SECURITY_TYPE_WPA3_SAE_TRANSITION = 2; 425 426 /** 427 * The definition of security type WPA3-SAE. 428 */ 429 public static final int SECURITY_TYPE_WPA3_SAE = 3; 430 431 /** 432 * The definition of security type WPA3-OWE Transition. 433 */ 434 public static final int SECURITY_TYPE_WPA3_OWE_TRANSITION = 4; 435 436 /** 437 * The definition of security type WPA3-OWE. 438 */ 439 public static final int SECURITY_TYPE_WPA3_OWE = 5; 440 441 /** @hide */ 442 @Retention(RetentionPolicy.SOURCE) 443 @IntDef(prefix = { "SECURITY_TYPE_" }, value = { 444 SECURITY_TYPE_OPEN, 445 SECURITY_TYPE_WPA2_PSK, 446 SECURITY_TYPE_WPA3_SAE_TRANSITION, 447 SECURITY_TYPE_WPA3_SAE, 448 SECURITY_TYPE_WPA3_OWE_TRANSITION, 449 SECURITY_TYPE_WPA3_OWE, 450 }) 451 public @interface SecurityType {} 452 453 /** Private constructor for Builder and Parcelable implementation. */ SoftApConfiguration( @ullable WifiSsid ssid, @Nullable MacAddress bssid, @Nullable String passphrase, boolean hiddenSsid, @NonNull SparseIntArray channels, @SecurityType int securityType, int maxNumberOfClients, boolean shutdownTimeoutEnabled, long shutdownTimeoutMillis, boolean clientControlByUser, @NonNull List<MacAddress> blockedList, @NonNull List<MacAddress> allowedList, int macRandomizationSetting, boolean bridgedModeOpportunisticShutdownEnabled, boolean ieee80211axEnabled, boolean ieee80211beEnabled, boolean isUserConfiguration, long bridgedModeOpportunisticShutdownTimeoutMillis, @NonNull List<ScanResult.InformationElement> vendorElements, @Nullable MacAddress persistentRandomizedMacAddress, @NonNull Set<Integer> allowedAcsChannels24g, @NonNull Set<Integer> allowedAcsChannels5g, @NonNull Set<Integer> allowedAcsChannels6g, @WifiAnnotations.Bandwidth int maxChannelBandwidth, @Nullable List<OuiKeyedData> vendorData, boolean isClientIsolationEnabled)454 private SoftApConfiguration( 455 @Nullable WifiSsid ssid, 456 @Nullable MacAddress bssid, 457 @Nullable String passphrase, 458 boolean hiddenSsid, 459 @NonNull SparseIntArray channels, 460 @SecurityType int securityType, 461 int maxNumberOfClients, 462 boolean shutdownTimeoutEnabled, 463 long shutdownTimeoutMillis, 464 boolean clientControlByUser, 465 @NonNull List<MacAddress> blockedList, 466 @NonNull List<MacAddress> allowedList, 467 int macRandomizationSetting, 468 boolean bridgedModeOpportunisticShutdownEnabled, 469 boolean ieee80211axEnabled, 470 boolean ieee80211beEnabled, 471 boolean isUserConfiguration, 472 long bridgedModeOpportunisticShutdownTimeoutMillis, 473 @NonNull List<ScanResult.InformationElement> vendorElements, 474 @Nullable MacAddress persistentRandomizedMacAddress, 475 @NonNull Set<Integer> allowedAcsChannels24g, 476 @NonNull Set<Integer> allowedAcsChannels5g, 477 @NonNull Set<Integer> allowedAcsChannels6g, 478 @WifiAnnotations.Bandwidth int maxChannelBandwidth, 479 @Nullable List<OuiKeyedData> vendorData, 480 boolean isClientIsolationEnabled) { 481 mWifiSsid = ssid; 482 mBssid = bssid; 483 mPassphrase = passphrase; 484 mHiddenSsid = hiddenSsid; 485 if (channels.size() != 0) { 486 mChannels = channels.clone(); 487 } else { 488 mChannels = new SparseIntArray(1); 489 mChannels.put(BAND_2GHZ, 0); 490 } 491 mSecurityType = securityType; 492 mMaxNumberOfClients = maxNumberOfClients; 493 mAutoShutdownEnabled = shutdownTimeoutEnabled; 494 mShutdownTimeoutMillis = shutdownTimeoutMillis; 495 mClientControlByUser = clientControlByUser; 496 mBlockedClientList = new ArrayList<>(blockedList); 497 mAllowedClientList = new ArrayList<>(allowedList); 498 mMacRandomizationSetting = macRandomizationSetting; 499 mBridgedModeOpportunisticShutdownEnabled = bridgedModeOpportunisticShutdownEnabled; 500 mIeee80211axEnabled = ieee80211axEnabled; 501 mIeee80211beEnabled = ieee80211beEnabled; 502 mIsUserConfiguration = isUserConfiguration; 503 mBridgedModeOpportunisticShutdownTimeoutMillis = 504 bridgedModeOpportunisticShutdownTimeoutMillis; 505 mVendorElements = new ArrayList<>(vendorElements); 506 mPersistentRandomizedMacAddress = persistentRandomizedMacAddress; 507 mAllowedAcsChannels2g = new HashSet<>(allowedAcsChannels24g); 508 mAllowedAcsChannels5g = new HashSet<>(allowedAcsChannels5g); 509 mAllowedAcsChannels6g = new HashSet<>(allowedAcsChannels6g); 510 mMaxChannelBandwidth = maxChannelBandwidth; 511 mVendorData = new ArrayList<>(vendorData); 512 mIsClientIsolationEnabled = isClientIsolationEnabled; 513 } 514 515 @Override equals(Object otherObj)516 public boolean equals(Object otherObj) { 517 if (this == otherObj) { 518 return true; 519 } 520 if (!(otherObj instanceof SoftApConfiguration)) { 521 return false; 522 } 523 SoftApConfiguration other = (SoftApConfiguration) otherObj; 524 return Objects.equals(mWifiSsid, other.mWifiSsid) 525 && Objects.equals(mBssid, other.mBssid) 526 && Objects.equals(mPassphrase, other.mPassphrase) 527 && mHiddenSsid == other.mHiddenSsid 528 && mChannels.toString().equals(other.mChannels.toString()) 529 && mSecurityType == other.mSecurityType 530 && mMaxNumberOfClients == other.mMaxNumberOfClients 531 && mAutoShutdownEnabled == other.mAutoShutdownEnabled 532 && mShutdownTimeoutMillis == other.mShutdownTimeoutMillis 533 && mClientControlByUser == other.mClientControlByUser 534 && Objects.equals(mBlockedClientList, other.mBlockedClientList) 535 && Objects.equals(mAllowedClientList, other.mAllowedClientList) 536 && mMacRandomizationSetting == other.mMacRandomizationSetting 537 && mBridgedModeOpportunisticShutdownEnabled 538 == other.mBridgedModeOpportunisticShutdownEnabled 539 && mIeee80211axEnabled == other.mIeee80211axEnabled 540 && mIeee80211beEnabled == other.mIeee80211beEnabled 541 && mIsUserConfiguration == other.mIsUserConfiguration 542 && mBridgedModeOpportunisticShutdownTimeoutMillis 543 == other.mBridgedModeOpportunisticShutdownTimeoutMillis 544 && Objects.equals(mVendorElements, other.mVendorElements) 545 && Objects.equals( 546 mPersistentRandomizedMacAddress, other.mPersistentRandomizedMacAddress) 547 && Objects.equals(mAllowedAcsChannels2g, other.mAllowedAcsChannels2g) 548 && Objects.equals(mAllowedAcsChannels5g, other.mAllowedAcsChannels5g) 549 && Objects.equals(mAllowedAcsChannels6g, other.mAllowedAcsChannels6g) 550 && mMaxChannelBandwidth == other.mMaxChannelBandwidth 551 && Objects.equals(mVendorData, other.mVendorData) 552 && mIsClientIsolationEnabled == other.mIsClientIsolationEnabled; 553 } 554 555 @Override hashCode()556 public int hashCode() { 557 return Objects.hash( 558 mWifiSsid, 559 mBssid, 560 mPassphrase, 561 mHiddenSsid, 562 mChannels.toString(), 563 mSecurityType, 564 mMaxNumberOfClients, 565 mAutoShutdownEnabled, 566 mShutdownTimeoutMillis, 567 mClientControlByUser, 568 mBlockedClientList, 569 mAllowedClientList, 570 mMacRandomizationSetting, 571 mBridgedModeOpportunisticShutdownEnabled, 572 mIeee80211axEnabled, 573 mIeee80211beEnabled, 574 mIsUserConfiguration, 575 mBridgedModeOpportunisticShutdownTimeoutMillis, 576 mVendorElements, 577 mPersistentRandomizedMacAddress, 578 mAllowedAcsChannels2g, 579 mAllowedAcsChannels5g, 580 mAllowedAcsChannels6g, 581 mMaxChannelBandwidth, 582 mVendorData, 583 mIsClientIsolationEnabled); 584 } 585 586 @Override toString()587 public String toString() { 588 StringBuilder sbuf = new StringBuilder(); 589 sbuf.append("ssid = ").append(mWifiSsid == null ? null : mWifiSsid.toString()); 590 if (mBssid != null) sbuf.append(" \n bssid = ").append(mBssid.toString()); 591 sbuf.append(" \n Passphrase = ").append( 592 TextUtils.isEmpty(mPassphrase) ? "<empty>" : "<non-empty>"); 593 sbuf.append(" \n HiddenSsid = ").append(mHiddenSsid); 594 sbuf.append(" \n Channels = ").append(mChannels); 595 sbuf.append(" \n SecurityType = ").append(getSecurityType()); 596 sbuf.append(" \n MaxClient = ").append(mMaxNumberOfClients); 597 sbuf.append(" \n AutoShutdownEnabled = ").append(mAutoShutdownEnabled); 598 sbuf.append(" \n ShutdownTimeoutMillis = ").append(mShutdownTimeoutMillis); 599 sbuf.append(" \n ClientControlByUser = ").append(mClientControlByUser); 600 sbuf.append(" \n BlockedClientList = ").append(mBlockedClientList); 601 sbuf.append(" \n AllowedClientList= ").append(mAllowedClientList); 602 sbuf.append(" \n MacRandomizationSetting = ").append(mMacRandomizationSetting); 603 sbuf.append(" \n BridgedModeInstanceOpportunisticEnabled = ") 604 .append(mBridgedModeOpportunisticShutdownEnabled); 605 sbuf.append(" \n BridgedModeOpportunisticShutdownTimeoutMillis = ") 606 .append(mBridgedModeOpportunisticShutdownTimeoutMillis); 607 sbuf.append(" \n Ieee80211axEnabled = ").append(mIeee80211axEnabled); 608 sbuf.append(" \n Ieee80211beEnabled = ").append(mIeee80211beEnabled); 609 sbuf.append(" \n isUserConfiguration = ").append(mIsUserConfiguration); 610 sbuf.append(" \n vendorElements = ").append(mVendorElements); 611 sbuf.append(" \n mPersistentRandomizedMacAddress = ") 612 .append(mPersistentRandomizedMacAddress); 613 sbuf.append(" \n mAllowedAcsChannels2g = ").append(mAllowedAcsChannels2g); 614 sbuf.append(" \n mAllowedAcsChannels5g = ").append(mAllowedAcsChannels5g); 615 sbuf.append(" \n mAllowedAcsChannels6g = ").append(mAllowedAcsChannels6g); 616 sbuf.append(" \n mMaxChannelBandwidth = ").append(mMaxChannelBandwidth); 617 sbuf.append(" \n mVendorData = ").append(mVendorData); 618 sbuf.append(" \n mIsClientIsolationEnabled = ").append(mIsClientIsolationEnabled); 619 return sbuf.toString(); 620 } 621 622 @Override writeToParcel(@onNull Parcel dest, int flags)623 public void writeToParcel(@NonNull Parcel dest, int flags) { 624 dest.writeParcelable(mWifiSsid, 0); 625 dest.writeParcelable(mBssid, flags); 626 dest.writeString(mPassphrase); 627 dest.writeBoolean(mHiddenSsid); 628 writeSparseIntArray(dest, mChannels); 629 dest.writeInt(mSecurityType); 630 dest.writeInt(mMaxNumberOfClients); 631 dest.writeBoolean(mAutoShutdownEnabled); 632 dest.writeLong(mShutdownTimeoutMillis); 633 dest.writeBoolean(mClientControlByUser); 634 dest.writeTypedList(mBlockedClientList); 635 dest.writeTypedList(mAllowedClientList); 636 dest.writeInt(mMacRandomizationSetting); 637 dest.writeBoolean(mBridgedModeOpportunisticShutdownEnabled); 638 dest.writeBoolean(mIeee80211axEnabled); 639 dest.writeBoolean(mIeee80211beEnabled); 640 dest.writeBoolean(mIsUserConfiguration); 641 dest.writeLong(mBridgedModeOpportunisticShutdownTimeoutMillis); 642 dest.writeTypedList(mVendorElements); 643 dest.writeParcelable(mPersistentRandomizedMacAddress, flags); 644 writeHashSetInt(dest, mAllowedAcsChannels2g); 645 writeHashSetInt(dest, mAllowedAcsChannels5g); 646 writeHashSetInt(dest, mAllowedAcsChannels6g); 647 dest.writeInt(mMaxChannelBandwidth); 648 dest.writeList(mVendorData); 649 dest.writeBoolean(mIsClientIsolationEnabled); 650 } 651 652 /* Reference from frameworks/base/core/java/android/os/Parcel.java */ writeSparseIntArray(@onNull Parcel dest, @Nullable SparseIntArray val)653 private static void writeSparseIntArray(@NonNull Parcel dest, 654 @Nullable SparseIntArray val) { 655 if (val == null) { 656 dest.writeInt(-1); 657 return; 658 } 659 int n = val.size(); 660 dest.writeInt(n); 661 int i = 0; 662 while (i < n) { 663 dest.writeInt(val.keyAt(i)); 664 dest.writeInt(val.valueAt(i)); 665 i++; 666 } 667 } 668 669 /* Reference from frameworks/base/core/java/android/os/Parcel.java */ 670 @NonNull readSparseIntArray(@onNull Parcel in)671 private static SparseIntArray readSparseIntArray(@NonNull Parcel in) { 672 int n = in.readInt(); 673 if (n < 0) { 674 return new SparseIntArray(); 675 } 676 SparseIntArray sa = new SparseIntArray(n); 677 while (n > 0) { 678 int key = in.readInt(); 679 int value = in.readInt(); 680 sa.append(key, value); 681 n--; 682 } 683 return sa; 684 } 685 686 /* Write HashSet<Integer> into Parcel */ writeHashSetInt(@onNull Parcel dest, @NonNull Set<Integer> set)687 private static void writeHashSetInt(@NonNull Parcel dest, @NonNull Set<Integer> set) { 688 if (set.isEmpty()) { 689 dest.writeInt(-1); 690 return; 691 } 692 693 dest.writeInt(set.size()); 694 for (int val : set) { 695 dest.writeInt(val); 696 } 697 } 698 699 /* Read HashSet<Integer> from Parcel */ 700 @NonNull readHashSetInt(@onNull Parcel in)701 private static Set<Integer> readHashSetInt(@NonNull Parcel in) { 702 Set<Integer> set = new HashSet<>(); 703 int len = in.readInt(); 704 if (len < 0) { 705 return set; 706 } 707 708 for (int i = 0; i < len; i++) { 709 set.add(in.readInt()); 710 } 711 return set; 712 } 713 714 /* Read List<OuiKeyedData> from Parcel */ 715 @NonNull readOuiKeyedDataList(@onNull Parcel in)716 private static List<OuiKeyedData> readOuiKeyedDataList(@NonNull Parcel in) { 717 List<OuiKeyedData> dataList = new ArrayList<>(); 718 if (SdkLevel.isAtLeastT()) { 719 in.readList(dataList, OuiKeyedData.class.getClassLoader(), OuiKeyedData.class); 720 } else { 721 in.readList(dataList, OuiKeyedData.class.getClassLoader()); 722 } 723 return dataList; 724 } 725 726 @Override describeContents()727 public int describeContents() { 728 return 0; 729 } 730 731 @NonNull 732 public static final Creator<SoftApConfiguration> CREATOR = 733 new Creator<SoftApConfiguration>() { 734 @Override 735 public SoftApConfiguration createFromParcel(Parcel in) { 736 return new SoftApConfiguration( 737 in.readParcelable(WifiSsid.class.getClassLoader()), 738 in.readParcelable(MacAddress.class.getClassLoader()), 739 in.readString(), 740 in.readBoolean(), 741 readSparseIntArray(in), 742 in.readInt(), 743 in.readInt(), 744 in.readBoolean(), 745 in.readLong(), 746 in.readBoolean(), 747 in.createTypedArrayList(MacAddress.CREATOR), 748 in.createTypedArrayList(MacAddress.CREATOR), 749 in.readInt(), 750 in.readBoolean(), 751 in.readBoolean(), 752 in.readBoolean(), 753 in.readBoolean(), 754 in.readLong(), 755 in.createTypedArrayList(ScanResult.InformationElement.CREATOR), 756 in.readParcelable(MacAddress.class.getClassLoader()), 757 readHashSetInt(in), 758 readHashSetInt(in), 759 readHashSetInt(in), 760 in.readInt(), 761 readOuiKeyedDataList(in), 762 in.readBoolean()); 763 } 764 765 @Override 766 public SoftApConfiguration[] newArray(int size) { 767 return new SoftApConfiguration[size]; 768 } 769 }; 770 771 /** 772 * Return the UTF-8 String set to be the SSID for the AP. If the SSID cannot be decoded as 773 * UTF-8, then this will return {@link WifiManager#UNKNOWN_SSID}. 774 * 775 * @deprecated Use {@link #getWifiSsid()} instead. 776 */ 777 @Nullable 778 @Deprecated getSsid()779 public String getSsid() { 780 if (mWifiSsid == null) { 781 return null; 782 } 783 CharSequence utf8Text = mWifiSsid.getUtf8Text(); 784 return utf8Text != null ? utf8Text.toString() : WifiManager.UNKNOWN_SSID; 785 } 786 787 /** 788 * Return WifiSsid set to be the SSID for the AP. 789 */ 790 @Nullable getWifiSsid()791 public WifiSsid getWifiSsid() { 792 return mWifiSsid; 793 } 794 795 /** 796 * Return VendorElements for the AP. 797 * @hide 798 */ 799 @NonNull 800 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 801 @SystemApi getVendorElements()802 public List<ScanResult.InformationElement> getVendorElements() { 803 if (!SdkLevel.isAtLeastT()) { 804 throw new UnsupportedOperationException(); 805 } 806 return getVendorElementsInternal(); 807 } 808 809 /** 810 * @see #getVendorElements() 811 * @hide 812 */ getVendorElementsInternal()813 public List<ScanResult.InformationElement> getVendorElementsInternal() { 814 return new ArrayList<>(mVendorElements); 815 } 816 817 /** 818 * Returns MAC address set to be BSSID for the AP. 819 */ 820 @Nullable getBssid()821 public MacAddress getBssid() { 822 return mBssid; 823 } 824 825 /** 826 * Returns String set to be passphrase for current AP. 827 */ 828 @Nullable getPassphrase()829 public String getPassphrase() { 830 return mPassphrase; 831 } 832 833 /** 834 * Returns Boolean set to be indicate hidden (true: doesn't broadcast its SSID) or 835 * not (false: broadcasts its SSID) for the AP. 836 */ isHiddenSsid()837 public boolean isHiddenSsid() { 838 return mHiddenSsid; 839 } 840 841 /** 842 * Returns band type set to be the band for the AP. 843 * 844 * One or combination of {@code BAND_}, for instance 845 * {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, or {@code BAND_2GHZ | BAND_5GHZ}. 846 * 847 * Note: Returns the lowest band when more than one band is set. 848 * Use {@link #getChannels()} to get dual bands setting. 849 * 850 * See also {@link Builder#setBand(int)}. 851 * 852 * @deprecated This API is deprecated. Use {@link #getChannels()} instead. 853 * @hide 854 */ 855 @Deprecated 856 @SystemApi getBand()857 public @BandType int getBand() { 858 return mChannels.keyAt(0); 859 } 860 861 /** 862 * Returns a sorted array in ascending order that consists of the configured band types 863 * for the APs. 864 * 865 * The band type is one or combination of {@code BAND_}, for instance 866 * {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, or {@code BAND_2GHZ | BAND_5GHZ}. 867 * 868 * Note: return array may only include one band when current setting is single AP mode. 869 * See also {@link Builder#setBands(int[])}. 870 * 871 * @hide 872 */ 873 @Keep getBands()874 public @NonNull int[] getBands() { 875 int[] bands = new int[mChannels.size()]; 876 for (int i = 0; i < bands.length; i++) { 877 bands[i] = mChannels.keyAt(i); 878 } 879 return bands; 880 } 881 882 /** 883 * Returns Integer set to be the channel for the AP. 884 * 885 * Note: Returns the channel which associated to the lowest band if more than one channel 886 * is set. Use {@link Builder#getChannels()} to get dual channel setting. 887 * See also {@link Builder#setChannel(int, int)}. 888 * 889 * @deprecated This API is deprecated. Use {@link #getChannels()} instead. 890 * @hide 891 */ 892 @Deprecated 893 @SystemApi getChannel()894 public int getChannel() { 895 return mChannels.valueAt(0); 896 } 897 898 899 /** 900 * Returns SparseIntArray (key: {@code BandType} , value: channel) that consists of 901 * the configured bands and channels for the AP(s). 902 * 903 * The returned channel value is Wi-Fi channel numbering. 904 * Reference the Wi-Fi channel numbering and the channelization in IEEE 802.11-2016 905 * specifications, section 17.3.8.4.2, 17.3.8.4.3 and Table 15-6. 906 * 907 * Note: return array may only include one channel when current setting is single AP mode. 908 * See also {@link Builder#setChannels(SparseIntArray)}. 909 */ 910 @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS) 911 @RequiresApi(Build.VERSION_CODES.S) getChannels()912 public @NonNull SparseIntArray getChannels() { 913 if (!SdkLevel.isAtLeastS()) { 914 throw new UnsupportedOperationException(); 915 } 916 return mChannels.clone(); 917 } 918 919 /** 920 * Get security type params which depends on which security passphrase to set. 921 * 922 * @return One of: 923 * {@link #SECURITY_TYPE_OPEN}, 924 * {@link #SECURITY_TYPE_WPA2_PSK}, 925 * {@link #SECURITY_TYPE_WPA3_SAE_TRANSITION}, 926 * {@link #SECURITY_TYPE_WPA3_SAE}, 927 * {@link #SECURITY_TYPE_WPA3_OWE_TRANSITION}, 928 * {@link #SECURITY_TYPE_WPA3_OWE} 929 */ getSecurityType()930 public @SecurityType int getSecurityType() { 931 return mSecurityType; 932 } 933 934 /** 935 * Returns the maximum number of clients that can associate to the AP. 936 * See also {@link Builder#setMaxNumberOfClients(int)}. 937 * 938 * @hide 939 */ 940 @SystemApi getMaxNumberOfClients()941 public int getMaxNumberOfClients() { 942 return mMaxNumberOfClients; 943 } 944 945 /** 946 * Returns whether auto shutdown is enabled or not. 947 * The Soft AP will shutdown when there are no devices associated to it for 948 * the timeout duration. See also {@link Builder#setAutoShutdownEnabled(boolean)}. 949 * 950 * @hide 951 */ 952 @SystemApi isAutoShutdownEnabled()953 public boolean isAutoShutdownEnabled() { 954 return mAutoShutdownEnabled; 955 } 956 957 /** 958 * Returns the shutdown timeout in milliseconds. 959 * The Soft AP will shutdown when there are no devices associated to it for 960 * the timeout duration. See also {@link Builder#setShutdownTimeoutMillis(long)}. 961 * 962 * @hide 963 */ 964 @SystemApi getShutdownTimeoutMillis()965 public long getShutdownTimeoutMillis() { 966 if (!CompatChanges.isChangeEnabled( 967 REMOVE_ZERO_FOR_TIMEOUT_SETTING) && mShutdownTimeoutMillis == DEFAULT_TIMEOUT) { 968 // For legacy application, return 0 when setting is DEFAULT_TIMEOUT. 969 return 0; 970 } 971 return mShutdownTimeoutMillis; 972 } 973 974 /** 975 * Returns a flag indicating whether clients need to be pre-approved by the user. 976 * (true: authorization required) or not (false: not required). 977 * See also {@link Builder#setClientControlByUserEnabled(Boolean)}. 978 * 979 * @return true when client isolation is enable. 980 * 981 * @hide 982 */ 983 @SystemApi isClientControlByUserEnabled()984 public boolean isClientControlByUserEnabled() { 985 return mClientControlByUser; 986 } 987 988 /** 989 * Returns List of clients which aren't allowed to associate to the AP. 990 * 991 * Clients are configured using {@link Builder#setBlockedClientList(List)} 992 * 993 * @hide 994 */ 995 @NonNull 996 @SystemApi getBlockedClientList()997 public List<MacAddress> getBlockedClientList() { 998 return mBlockedClientList; 999 } 1000 1001 /** 1002 * List of clients which are allowed to associate to the AP. 1003 * Clients are configured using {@link Builder#setAllowedClientList(List)} 1004 * 1005 * @hide 1006 */ 1007 @NonNull 1008 @SystemApi getAllowedClientList()1009 public List<MacAddress> getAllowedClientList() { 1010 return mAllowedClientList; 1011 } 1012 1013 /** 1014 * Returns the level of MAC randomization for the AP BSSID. 1015 * See also {@link Builder#setMacRandomizationSetting(int)}. 1016 * 1017 * @hide 1018 */ 1019 @RequiresApi(Build.VERSION_CODES.S) 1020 @SystemApi 1021 @MacRandomizationSetting getMacRandomizationSetting()1022 public int getMacRandomizationSetting() { 1023 if (!SdkLevel.isAtLeastS()) { 1024 throw new UnsupportedOperationException(); 1025 } 1026 return getMacRandomizationSettingInternal(); 1027 } 1028 1029 /** 1030 * @hide 1031 */ 1032 @MacRandomizationSetting getMacRandomizationSettingInternal()1033 public int getMacRandomizationSettingInternal() { 1034 return mMacRandomizationSetting; 1035 } 1036 1037 /** 1038 * Returns whether opportunistic shutdown of an instance in bridged AP is enabled or not. 1039 * 1040 * See also {@link Builder#setBridgedModeOpportunisticShutdownEnabled(boolean}} 1041 * @hide 1042 */ 1043 @RequiresApi(Build.VERSION_CODES.S) 1044 @SystemApi isBridgedModeOpportunisticShutdownEnabled()1045 public boolean isBridgedModeOpportunisticShutdownEnabled() { 1046 if (!SdkLevel.isAtLeastS()) { 1047 throw new UnsupportedOperationException(); 1048 } 1049 return isBridgedModeOpportunisticShutdownEnabledInternal(); 1050 } 1051 1052 /** 1053 * @see #isBridgedModeOpportunisticShutdownEnabled() 1054 * @hide 1055 */ isBridgedModeOpportunisticShutdownEnabledInternal()1056 public boolean isBridgedModeOpportunisticShutdownEnabledInternal() { 1057 return mBridgedModeOpportunisticShutdownEnabled; 1058 } 1059 1060 /** 1061 * @see #isIeee80211axEnabled() 1062 * @hide 1063 */ isIeee80211axEnabledInternal()1064 public boolean isIeee80211axEnabledInternal() { 1065 return mIeee80211axEnabled; 1066 } 1067 1068 /** 1069 * Returns whether or not 802.11ax is enabled on the SoftAP. 1070 * This is an indication that if the device support 802.11ax AP then to enable or disable 1071 * that feature. If the device does not support 802.11ax AP then this flag is ignored. 1072 * See also {@link Builder#setIeee80211axEnabled(boolean}} 1073 * @hide 1074 */ 1075 @RequiresApi(Build.VERSION_CODES.S) 1076 @SystemApi isIeee80211axEnabled()1077 public boolean isIeee80211axEnabled() { 1078 if (!SdkLevel.isAtLeastS()) { 1079 throw new UnsupportedOperationException(); 1080 } 1081 return isIeee80211axEnabledInternal(); 1082 } 1083 1084 /** 1085 * Returns whether or not the Soft AP is configured to enable 802.11be. 1086 * This is an indication that if the device support 802.11be AP then to enable or disable 1087 * that feature. If the device does not support 802.11be AP then this flag is ignored. 1088 * See also {@link Builder#setIeee80211beEnabled(boolean}} 1089 * @hide 1090 */ 1091 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 1092 @SystemApi isIeee80211beEnabled()1093 public boolean isIeee80211beEnabled() { 1094 if (!SdkLevel.isAtLeastT()) { 1095 throw new UnsupportedOperationException(); 1096 } 1097 return mIeee80211beEnabled; 1098 } 1099 1100 /** 1101 * Returns the allowed channels for ACS in a selected band. 1102 * 1103 * If an empty array is returned, then all channels in that band are allowed 1104 * The channels are configured using {@link Builder#setAllowedAcsChannels(int, int[])} 1105 * 1106 * @param band one of the following band types: 1107 * {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, {@link #BAND_6GHZ}. 1108 * 1109 * @return array of the allowed channels for ACS in that band 1110 * 1111 * @hide 1112 */ 1113 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 1114 @NonNull 1115 @SystemApi getAllowedAcsChannels(@andType int band)1116 public int[] getAllowedAcsChannels(@BandType int band) { 1117 if (!SdkLevel.isAtLeastT()) { 1118 throw new UnsupportedOperationException(); 1119 } 1120 switch(band) { 1121 case BAND_2GHZ: 1122 return mAllowedAcsChannels2g.stream().mapToInt(Integer::intValue).toArray(); 1123 case BAND_5GHZ: 1124 return mAllowedAcsChannels5g.stream().mapToInt(Integer::intValue).toArray(); 1125 case BAND_6GHZ: 1126 return mAllowedAcsChannels6g.stream().mapToInt(Integer::intValue).toArray(); 1127 default: 1128 throw new IllegalArgumentException("getAllowedAcsChannels: Invalid band: " + band); 1129 } 1130 } 1131 1132 /** 1133 * Returns configured maximum channel bandwidth for the SoftAp connection. 1134 * 1135 * If not configured, it will return {@link SoftApInfo#CHANNEL_WIDTH_AUTO} 1136 * 1137 * @hide 1138 */ 1139 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 1140 @SystemApi getMaxChannelBandwidth()1141 public @WifiAnnotations.Bandwidth int getMaxChannelBandwidth() { 1142 if (!SdkLevel.isAtLeastT()) { 1143 throw new UnsupportedOperationException(); 1144 } 1145 return mMaxChannelBandwidth; 1146 } 1147 1148 /** 1149 * Returns whether or not the {@link SoftApConfiguration} was configured by the user 1150 * (as opposed to the default system configuration). 1151 * <p> 1152 * The {@link SoftApConfiguration} is considered user edited once the 1153 * {@link WifiManager#setSoftApConfiguration(SoftApConfiguration)} is called 1154 * - whether or not that configuration is the same as the default system configuration! 1155 * 1156 * @hide 1157 */ 1158 @RequiresApi(Build.VERSION_CODES.S) 1159 @SystemApi isUserConfiguration()1160 public boolean isUserConfiguration() { 1161 if (!SdkLevel.isAtLeastS()) { 1162 throw new UnsupportedOperationException(); 1163 } 1164 return isUserConfigurationInternal(); 1165 } 1166 1167 /** 1168 * Returns the randomized MAC address to be used by this configuration. 1169 * 1170 * The Soft AP may be configured to use a persistent randomized MAC address with 1171 * {@link Builder#setMacRandomizationSetting(int)}. This method returns the persistent 1172 * randomized MAC address which will be used for the Soft AP controlled by this configuration. 1173 * 1174 * @hide 1175 */ 1176 @SystemApi getPersistentRandomizedMacAddress()1177 public @NonNull MacAddress getPersistentRandomizedMacAddress() { 1178 return mPersistentRandomizedMacAddress; 1179 } 1180 1181 /** 1182 * @hide 1183 */ isUserConfigurationInternal()1184 public boolean isUserConfigurationInternal() { 1185 return mIsUserConfiguration; 1186 } 1187 1188 /** 1189 * Returns the bridged mode opportunistic shutdown timeout in milliseconds. 1190 * An instance in bridged AP will shutdown when there is no device associated to it for 1191 * the timeout duration. See also 1192 * {@link Builder#setBridgedModeOpportunisticShutdownTimeoutMillis(long)}. 1193 * 1194 * @hide 1195 */ 1196 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 1197 @SystemApi getBridgedModeOpportunisticShutdownTimeoutMillis()1198 public long getBridgedModeOpportunisticShutdownTimeoutMillis() { 1199 if (!SdkLevel.isAtLeastT()) { 1200 throw new UnsupportedOperationException(); 1201 } 1202 return mBridgedModeOpportunisticShutdownTimeoutMillis; 1203 } 1204 1205 1206 /** 1207 * @hide 1208 */ getBridgedModeOpportunisticShutdownTimeoutMillisInternal()1209 public long getBridgedModeOpportunisticShutdownTimeoutMillisInternal() { 1210 return mBridgedModeOpportunisticShutdownTimeoutMillis; 1211 } 1212 1213 /** 1214 * Return the vendor-provided configuration data, if it exists. See also {@link 1215 * Builder#setVendorData(List)} 1216 * 1217 * @return Vendor configuration data, or empty list if it does not exist. 1218 * @hide 1219 */ 1220 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 1221 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 1222 @NonNull 1223 @SystemApi getVendorData()1224 public List<OuiKeyedData> getVendorData() { 1225 if (!SdkLevel.isAtLeastV()) { 1226 throw new UnsupportedOperationException(); 1227 } 1228 return mVendorData; 1229 } 1230 1231 /** 1232 * Returns whether client isolation is enabled or not. 1233 * 1234 * Client isolation is used to disallow a connected Soft AP 1235 * client to communicate with other connected clients. 1236 * 1237 * @hide 1238 */ 1239 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 1240 @FlaggedApi(Flags.FLAG_AP_ISOLATE) 1241 @SystemApi isClientIsolationEnabled()1242 public boolean isClientIsolationEnabled() { 1243 if (!Environment.isSdkAtLeastB()) { 1244 throw new UnsupportedOperationException(); 1245 } 1246 return mIsClientIsolationEnabled; 1247 } 1248 1249 /** 1250 * Returns a {@link WifiConfiguration} representation of this {@link SoftApConfiguration}. 1251 * Note that SoftApConfiguration may contain configuration which is cannot be represented 1252 * by the legacy WifiConfiguration, in such cases a null will be returned. 1253 * 1254 * To maintain legacy behavior, the SSID of the WifiConfiguration will be the UTF-8 1255 * representation of the SSID without double quotes, as opposed to the double-quoted UTF-8 1256 * format documented in {@link WifiConfiguration#SSID}. If the SSID cannot be decoded as UTF-8, 1257 * then the SSID of the WifiConfiguration will be {@link WifiManager#UNKNOWN_SSID}. 1258 * 1259 * <li> SoftAp band in {@link WifiConfiguration.apBand} only supports 1260 * 2GHz, 5GHz, 2GHz+5GHz bands, so conversion is limited to these bands. </li> 1261 * 1262 * <li> SoftAp security type in {@link WifiConfiguration.KeyMgmt} only supports 1263 * NONE, WPA2_PSK, so conversion is limited to these security type.</li> 1264 * @hide 1265 */ 1266 @Nullable 1267 @SystemApi toWifiConfiguration()1268 public WifiConfiguration toWifiConfiguration() { 1269 WifiConfiguration wifiConfig = new WifiConfiguration(); 1270 CharSequence utf8Text = mWifiSsid != null ? mWifiSsid.getUtf8Text() : null; 1271 wifiConfig.SSID = utf8Text != null ? utf8Text.toString() : WifiManager.UNKNOWN_SSID; 1272 wifiConfig.preSharedKey = mPassphrase; 1273 wifiConfig.hiddenSSID = mHiddenSsid; 1274 wifiConfig.apChannel = getChannel(); 1275 switch (mSecurityType) { 1276 case SECURITY_TYPE_OPEN: 1277 wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 1278 break; 1279 case SECURITY_TYPE_WPA2_PSK: 1280 case SECURITY_TYPE_WPA3_SAE_TRANSITION: 1281 wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK); 1282 break; 1283 default: 1284 Log.e(TAG, "Convert fail, unsupported security type :" + mSecurityType); 1285 return null; 1286 } 1287 1288 switch (getBand()) { 1289 case BAND_2GHZ: 1290 wifiConfig.apBand = WifiConfiguration.AP_BAND_2GHZ; 1291 break; 1292 case BAND_5GHZ: 1293 wifiConfig.apBand = WifiConfiguration.AP_BAND_5GHZ; 1294 break; 1295 case BAND_2GHZ | BAND_5GHZ: 1296 wifiConfig.apBand = WifiConfiguration.AP_BAND_ANY; 1297 break; 1298 case BAND_ANY: 1299 wifiConfig.apBand = WifiConfiguration.AP_BAND_ANY; 1300 break; 1301 default: 1302 Log.e(TAG, "Convert fail, unsupported band setting :" + getBand()); 1303 return null; 1304 } 1305 return wifiConfig; 1306 } 1307 1308 /** 1309 * Builds a {@link SoftApConfiguration}, which allows an app to configure various aspects of a 1310 * Soft AP. 1311 * 1312 * All fields are optional. By default, SSID and BSSID are automatically chosen by the 1313 * framework, and an open network is created. 1314 */ 1315 @FlaggedApi(Flags.FLAG_PUBLIC_BANDS_FOR_LOHS) 1316 public static final class Builder { 1317 private WifiSsid mWifiSsid; 1318 private MacAddress mBssid; 1319 private String mPassphrase; 1320 private boolean mHiddenSsid; 1321 private SparseIntArray mChannels; 1322 private int mMaxNumberOfClients; 1323 private int mSecurityType; 1324 private boolean mAutoShutdownEnabled; 1325 private long mShutdownTimeoutMillis; 1326 private boolean mClientControlByUser; 1327 private List<MacAddress> mBlockedClientList; 1328 private List<MacAddress> mAllowedClientList; 1329 private int mMacRandomizationSetting; 1330 private boolean mBridgedModeOpportunisticShutdownEnabled; 1331 private boolean mIeee80211axEnabled; 1332 private boolean mIeee80211beEnabled; 1333 private boolean mIsUserConfiguration; 1334 private long mBridgedModeOpportunisticShutdownTimeoutMillis; 1335 private List<ScanResult.InformationElement> mVendorElements; 1336 private MacAddress mPersistentRandomizedMacAddress; 1337 private Set<Integer> mAllowedAcsChannels2g; 1338 private Set<Integer> mAllowedAcsChannels5g; 1339 private Set<Integer> mAllowedAcsChannels6g; 1340 private @WifiAnnotations.Bandwidth int mMaxChannelBandwidth; 1341 private @Nullable List<OuiKeyedData> mVendorData; 1342 private boolean mIsClientIsolationEnabled; 1343 1344 /** 1345 * Constructs a Builder with default values (see {@link Builder}). 1346 */ Builder()1347 public Builder() { 1348 mWifiSsid = null; 1349 mBssid = null; 1350 mPassphrase = null; 1351 mHiddenSsid = false; 1352 mChannels = new SparseIntArray(1); 1353 mChannels.put(BAND_2GHZ, 0); 1354 mMaxNumberOfClients = 0; 1355 mSecurityType = SECURITY_TYPE_OPEN; 1356 mAutoShutdownEnabled = true; // enabled by default. 1357 mShutdownTimeoutMillis = DEFAULT_TIMEOUT; 1358 mClientControlByUser = false; 1359 mBlockedClientList = new ArrayList<>(); 1360 mAllowedClientList = new ArrayList<>(); 1361 if (SdkLevel.isAtLeastT()) { 1362 mMacRandomizationSetting = RANDOMIZATION_NON_PERSISTENT; 1363 } else { 1364 mMacRandomizationSetting = RANDOMIZATION_PERSISTENT; 1365 } 1366 mBridgedModeOpportunisticShutdownEnabled = true; 1367 mIeee80211axEnabled = true; 1368 mIeee80211beEnabled = true; 1369 mIsUserConfiguration = true; 1370 mBridgedModeOpportunisticShutdownTimeoutMillis = DEFAULT_TIMEOUT; 1371 mVendorElements = new ArrayList<>(); 1372 mPersistentRandomizedMacAddress = null; 1373 mAllowedAcsChannels2g = new HashSet<>(); 1374 mAllowedAcsChannels5g = new HashSet<>(); 1375 mAllowedAcsChannels6g = new HashSet<>(); 1376 mMaxChannelBandwidth = SoftApInfo.CHANNEL_WIDTH_AUTO; 1377 mVendorData = new ArrayList<>(); 1378 mIsClientIsolationEnabled = false; 1379 } 1380 1381 /** 1382 * Constructs a Builder initialized from an existing {@link SoftApConfiguration} instance. 1383 * 1384 * @hide 1385 */ 1386 @SystemApi Builder(@onNull SoftApConfiguration other)1387 public Builder(@NonNull SoftApConfiguration other) { 1388 if (other == null) { 1389 Log.e(TAG, "Cannot provide a null SoftApConfiguration"); 1390 return; 1391 } 1392 1393 mWifiSsid = other.mWifiSsid; 1394 mBssid = other.mBssid; 1395 mPassphrase = other.mPassphrase; 1396 mHiddenSsid = other.mHiddenSsid; 1397 mChannels = other.mChannels.clone(); 1398 mMaxNumberOfClients = other.mMaxNumberOfClients; 1399 mSecurityType = other.mSecurityType; 1400 mAutoShutdownEnabled = other.mAutoShutdownEnabled; 1401 mShutdownTimeoutMillis = other.mShutdownTimeoutMillis; 1402 mClientControlByUser = other.mClientControlByUser; 1403 mBlockedClientList = new ArrayList<>(other.mBlockedClientList); 1404 mAllowedClientList = new ArrayList<>(other.mAllowedClientList); 1405 mMacRandomizationSetting = other.mMacRandomizationSetting; 1406 mBridgedModeOpportunisticShutdownEnabled = 1407 other.mBridgedModeOpportunisticShutdownEnabled; 1408 mIeee80211axEnabled = other.mIeee80211axEnabled; 1409 mIeee80211beEnabled = other.mIeee80211beEnabled; 1410 mIsUserConfiguration = other.mIsUserConfiguration; 1411 mBridgedModeOpportunisticShutdownTimeoutMillis = 1412 other.mBridgedModeOpportunisticShutdownTimeoutMillis; 1413 mVendorElements = new ArrayList<>(other.mVendorElements); 1414 mPersistentRandomizedMacAddress = other.mPersistentRandomizedMacAddress; 1415 mAllowedAcsChannels2g = new HashSet<>(other.mAllowedAcsChannels2g); 1416 mAllowedAcsChannels5g = new HashSet<>(other.mAllowedAcsChannels5g); 1417 mAllowedAcsChannels6g = new HashSet<>(other.mAllowedAcsChannels6g); 1418 mMaxChannelBandwidth = other.mMaxChannelBandwidth; 1419 if (SdkLevel.isAtLeastS() && mBssid != null) { 1420 // Auto set correct MAC randomization setting for the legacy SoftApConfiguration 1421 // to avoid the exception happen when framework (system server) copy 1422 // SoftApConfiguration. 1423 mMacRandomizationSetting = RANDOMIZATION_NONE; 1424 } 1425 mVendorData = new ArrayList<>(other.mVendorData); 1426 mIsClientIsolationEnabled = other.mIsClientIsolationEnabled; 1427 } 1428 1429 /** 1430 * Builds the {@link SoftApConfiguration} without any check. 1431 * 1432 * @return A new {@link SoftApConfiguration}, as configured by previous method calls. 1433 * 1434 * @hide 1435 */ 1436 @VisibleForTesting 1437 @NonNull buildWithoutCheck()1438 public SoftApConfiguration buildWithoutCheck() { 1439 return new SoftApConfiguration( 1440 mWifiSsid, 1441 mBssid, 1442 mPassphrase, 1443 mHiddenSsid, 1444 mChannels, 1445 mSecurityType, 1446 mMaxNumberOfClients, 1447 mAutoShutdownEnabled, 1448 mShutdownTimeoutMillis, 1449 mClientControlByUser, 1450 mBlockedClientList, 1451 mAllowedClientList, 1452 mMacRandomizationSetting, 1453 mBridgedModeOpportunisticShutdownEnabled, 1454 mIeee80211axEnabled, 1455 mIeee80211beEnabled, 1456 mIsUserConfiguration, 1457 mBridgedModeOpportunisticShutdownTimeoutMillis, 1458 mVendorElements, 1459 mPersistentRandomizedMacAddress, 1460 mAllowedAcsChannels2g, 1461 mAllowedAcsChannels5g, 1462 mAllowedAcsChannels6g, 1463 mMaxChannelBandwidth, 1464 mVendorData, 1465 mIsClientIsolationEnabled); 1466 } 1467 1468 /** 1469 * Builds the {@link SoftApConfiguration}. 1470 * 1471 * @return A new {@link SoftApConfiguration}, as configured by previous method calls. 1472 */ 1473 @NonNull build()1474 public SoftApConfiguration build() { 1475 for (MacAddress client : mAllowedClientList) { 1476 if (mBlockedClientList.contains(client)) { 1477 throw new IllegalArgumentException("A MacAddress exist in both client list"); 1478 } 1479 } 1480 1481 // mMacRandomizationSetting supported from S. 1482 if (SdkLevel.isAtLeastS() && CompatChanges.isChangeEnabled( 1483 FORCE_MUTUAL_EXCLUSIVE_BSSID_MAC_RAMDONIZATION_SETTING) 1484 && mBssid != null && mMacRandomizationSetting != RANDOMIZATION_NONE) { 1485 throw new IllegalArgumentException("A BSSID had configured but MAC randomization" 1486 + " setting is not NONE"); 1487 } 1488 1489 if (!CompatChanges.isChangeEnabled( 1490 REMOVE_ZERO_FOR_TIMEOUT_SETTING) && mShutdownTimeoutMillis == DEFAULT_TIMEOUT) { 1491 mShutdownTimeoutMillis = 0; // Use 0 for legacy app. 1492 } 1493 1494 if (SdkLevel.isAtLeastB() && !mIeee80211axEnabled) { 1495 // Force 11BE to false since 11ax has dependency with 11AX. 1496 mIeee80211beEnabled = false; 1497 } 1498 return new SoftApConfiguration( 1499 mWifiSsid, 1500 mBssid, 1501 mPassphrase, 1502 mHiddenSsid, 1503 mChannels, 1504 mSecurityType, 1505 mMaxNumberOfClients, 1506 mAutoShutdownEnabled, 1507 mShutdownTimeoutMillis, 1508 mClientControlByUser, 1509 mBlockedClientList, 1510 mAllowedClientList, 1511 mMacRandomizationSetting, 1512 mBridgedModeOpportunisticShutdownEnabled, 1513 mIeee80211axEnabled, 1514 mIeee80211beEnabled, 1515 mIsUserConfiguration, 1516 mBridgedModeOpportunisticShutdownTimeoutMillis, 1517 mVendorElements, 1518 mPersistentRandomizedMacAddress, 1519 mAllowedAcsChannels2g, 1520 mAllowedAcsChannels5g, 1521 mAllowedAcsChannels6g, 1522 mMaxChannelBandwidth, 1523 mVendorData, 1524 mIsClientIsolationEnabled); 1525 } 1526 1527 /** 1528 * Specifies a UTF-8 SSID for the AP. 1529 * <p> 1530 * Null SSID only support when configure a local-only hotspot. 1531 * <p> 1532 * <li>If not set, defaults to null.</li> 1533 * 1534 * @param ssid SSID of valid Unicode characters, or null to have the SSID automatically 1535 * chosen by the framework. 1536 * @return Builder for chaining. 1537 * @throws IllegalArgumentException when the SSID is empty, not unicode, or if the byte 1538 * representation is longer than 32 bytes. 1539 * 1540 * @deprecated Use {@link #setWifiSsid(WifiSsid)} instead. 1541 * 1542 * @hide 1543 */ 1544 @NonNull 1545 @Deprecated 1546 @SystemApi setSsid(@ullable String ssid)1547 public Builder setSsid(@Nullable String ssid) { 1548 if (ssid == null) { 1549 mWifiSsid = null; 1550 return this; 1551 } 1552 1553 Preconditions.checkStringNotEmpty(ssid); 1554 Preconditions.checkArgument(StandardCharsets.UTF_8.newEncoder().canEncode(ssid)); 1555 mWifiSsid = WifiSsid.fromUtf8Text(ssid); 1556 return this; 1557 } 1558 1559 /** 1560 * Specifies an SSID for the AP in the form of WifiSsid. 1561 * <p> 1562 * Null SSID only support when configure a local-only hotspot. 1563 * <p> 1564 * <li>If not set, defaults to null.</li> 1565 * 1566 * @param wifiSsid SSID, or null ot have the SSID automatically chosen by the framework. 1567 * @return Builder for chaining. 1568 * 1569 * @hide 1570 */ 1571 @NonNull 1572 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 1573 @SystemApi setWifiSsid(@ullable WifiSsid wifiSsid)1574 public Builder setWifiSsid(@Nullable WifiSsid wifiSsid) { 1575 if (!SdkLevel.isAtLeastT()) { 1576 throw new UnsupportedOperationException(); 1577 } 1578 mWifiSsid = wifiSsid; 1579 return this; 1580 } 1581 1582 /** 1583 * Specify vendor-specific information elements for the (Soft) AP to transmit in its beacons 1584 * and probe responses. Method also validates the structure and throws 1585 * IllegalArgumentException in cases when ID of IE is not 0xDD (221) or incoming list 1586 * contain duplicate elements. 1587 * 1588 * @param vendorElements VendorElements 1589 * @return Builder for chaining. 1590 * 1591 * @hide 1592 */ 1593 @NonNull 1594 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 1595 @SystemApi setVendorElements( @onNull List<ScanResult.InformationElement> vendorElements)1596 public Builder setVendorElements( 1597 @NonNull List<ScanResult.InformationElement> vendorElements) { 1598 if (!SdkLevel.isAtLeastT()) { 1599 throw new UnsupportedOperationException(); 1600 } 1601 for (ScanResult.InformationElement e : vendorElements) { 1602 if (e.id != ScanResult.InformationElement.EID_VSA) { 1603 throw new IllegalArgumentException("received InformationElement which is not " 1604 + "related to VendorElements. VendorElement block should start with " 1605 + HexEncoding.encodeToString( 1606 new byte[]{ (byte) ScanResult.InformationElement.EID_VSA })); 1607 } 1608 } 1609 final HashSet<ScanResult.InformationElement> set = new HashSet<>(vendorElements); 1610 if (set.size() < vendorElements.size()) { 1611 throw new IllegalArgumentException("vendor elements array contain duplicates. " 1612 + "Please avoid passing duplicated and keep structure clean."); 1613 } 1614 mVendorElements = new ArrayList<>(vendorElements); 1615 return this; 1616 } 1617 1618 /** 1619 * Specifies a BSSID for the AP. 1620 * <p> 1621 * <li>If not set, defaults to null.</li> 1622 * 1623 * When this method is called, the caller needs to configure MAC randomization settings to 1624 * {@link #RANDOMIZATION_NONE}. See {@link #setMacRandomizationSetting(int)} for details. 1625 * 1626 * If multiple bands are requested via {@link #setBands(int[])} or 1627 * {@link #setChannels(SparseIntArray)}, HAL will derive 2 MAC addresses since framework 1628 * only sends down 1 MAC address. 1629 * 1630 * An example (but different implementation may perform a different mapping): 1631 * <li>MAC address 1: copy value of MAC address, 1632 * and set byte 1 = (0xFF - BSSID[1])</li> 1633 * <li>MAC address 2: copy value of MAC address, 1634 * and set byte 2 = (0xFF - BSSID[2])</li> 1635 * 1636 * Example BSSID argument: e2:38:60:c4:0e:b7 1637 * Derived MAC address 1: e2:c7:60:c4:0e:b7 1638 * Derived MAC address 2: e2:38:9f:c4:0e:b7 1639 * 1640 * <p> 1641 * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and 1642 * {@link SoftApCapability#areFeaturesSupported(long)} 1643 * with {@link SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION} to determine 1644 * whether or not this feature is supported. 1645 * 1646 * @param bssid BSSID, or null to have the BSSID chosen by the framework. The caller is 1647 * responsible for avoiding collisions. 1648 * @return Builder for chaining. 1649 * @throws IllegalArgumentException when the given BSSID is the all-zero 1650 * , multicast or broadcast MAC address. 1651 * 1652 * @hide 1653 */ 1654 @NonNull 1655 @SystemApi setBssid(@ullable MacAddress bssid)1656 public Builder setBssid(@Nullable MacAddress bssid) { 1657 if (bssid != null) { 1658 Preconditions.checkArgument(!bssid.equals(WifiManager.ALL_ZEROS_MAC_ADDRESS)); 1659 if (bssid.getAddressType() != MacAddress.TYPE_UNICAST) { 1660 throw new IllegalArgumentException("bssid doesn't support " 1661 + "multicast or broadcast mac address"); 1662 } 1663 } 1664 mBssid = bssid; 1665 return this; 1666 } 1667 1668 /** 1669 * Specifies that this AP should use specific security type with the given ASCII passphrase. 1670 * 1671 * @param securityType One of the following security types: 1672 * {@link #SECURITY_TYPE_OPEN}, 1673 * {@link #SECURITY_TYPE_WPA2_PSK}, 1674 * {@link #SECURITY_TYPE_WPA3_SAE_TRANSITION}, 1675 * {@link #SECURITY_TYPE_WPA3_SAE}, 1676 * {@link #SECURITY_TYPE_WPA3_OWE_TRANSITION}, 1677 * {@link #SECURITY_TYPE_WPA3_OWE}. 1678 * @param passphrase The passphrase to use for sepcific {@code securityType} configuration 1679 * or null with {@link #SECURITY_TYPE_OPEN}, {@link #SECURITY_TYPE_WPA3_OWE_TRANSITION}, 1680 * and {@link #SECURITY_TYPE_WPA3_OWE}. 1681 * 1682 * @return Builder for chaining. 1683 * @throws IllegalArgumentException when the passphrase is non-null for 1684 * - {@link #SECURITY_TYPE_OPEN} 1685 * - {@link #SECURITY_TYPE_WPA3_OWE_TRANSITION} 1686 * - {@link #SECURITY_TYPE_WPA3_OWE} 1687 * @throws IllegalArgumentException when the passphrase is empty for 1688 * - {@link #SECURITY_TYPE_WPA2_PSK}, 1689 * - {@link #SECURITY_TYPE_WPA3_SAE_TRANSITION}, 1690 * - {@link #SECURITY_TYPE_WPA3_SAE}, 1691 * @throws IllegalArgumentException before {@link android.os.Build.VERSION_CODES#TIRAMISU}) 1692 * when the passphrase is not between 8 and 63 bytes (inclusive) for 1693 * - {@link #SECURITY_TYPE_WPA2_PSK} 1694 * - {@link #SECURITY_TYPE_WPA3_SAE_TRANSITION} 1695 * 1696 * @hide 1697 */ 1698 @NonNull 1699 @SystemApi setPassphrase(@ullable String passphrase, @SecurityType int securityType)1700 public Builder setPassphrase(@Nullable String passphrase, @SecurityType int securityType) { 1701 if (!SdkLevel.isAtLeastT() 1702 && (securityType == SECURITY_TYPE_WPA3_OWE_TRANSITION 1703 || securityType == SECURITY_TYPE_WPA3_OWE)) { 1704 throw new UnsupportedOperationException(); 1705 } 1706 if (securityType == SECURITY_TYPE_OPEN 1707 || securityType == SECURITY_TYPE_WPA3_OWE_TRANSITION 1708 || securityType == SECURITY_TYPE_WPA3_OWE) { 1709 if (passphrase != null) { 1710 throw new IllegalArgumentException( 1711 "passphrase should be null when security type is open"); 1712 } 1713 } else { 1714 Preconditions.checkStringNotEmpty(passphrase); 1715 if (!SdkLevel.isAtLeastT() && (securityType == SECURITY_TYPE_WPA2_PSK 1716 || securityType == SECURITY_TYPE_WPA3_SAE_TRANSITION)) { 1717 int passphraseByteLength = 0; 1718 if (!TextUtils.isEmpty(passphrase)) { 1719 passphraseByteLength = passphrase.getBytes(StandardCharsets.UTF_8).length; 1720 } 1721 if (passphraseByteLength < PSK_MIN_LEN || passphraseByteLength > PSK_MAX_LEN) { 1722 throw new IllegalArgumentException( 1723 "Passphrase length must be at least " + PSK_MIN_LEN 1724 + " and no more than " + PSK_MAX_LEN 1725 + " for WPA2_PSK and WPA3_SAE_TRANSITION Mode"); 1726 } 1727 } 1728 } 1729 mSecurityType = securityType; 1730 mPassphrase = passphrase; 1731 return this; 1732 } 1733 1734 /** 1735 * Specifies whether the AP is hidden (doesn't broadcast its SSID) or 1736 * not (broadcasts its SSID). 1737 * <p> 1738 * <li>If not set, defaults to false (i.e not a hidden network).</li> 1739 * 1740 * @param hiddenSsid true for a hidden SSID, false otherwise. 1741 * @return Builder for chaining. 1742 * 1743 * @hide 1744 */ 1745 @NonNull 1746 @SystemApi setHiddenSsid(boolean hiddenSsid)1747 public Builder setHiddenSsid(boolean hiddenSsid) { 1748 mHiddenSsid = hiddenSsid; 1749 return this; 1750 } 1751 1752 /** 1753 * Specifies the band for the AP. 1754 * <p> 1755 * <li>If not set, defaults to {@link #BAND_2GHZ}.</li> 1756 * 1757 * @param band One or combination of the following band type: 1758 * {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, {@link #BAND_6GHZ}. 1759 * @return Builder for chaining. 1760 * @throws IllegalArgumentException when an invalid band type is provided. 1761 * 1762 * @hide 1763 */ 1764 @NonNull 1765 @SystemApi setBand(@andType int band)1766 public Builder setBand(@BandType int band) { 1767 if (!isBandValid(band)) { 1768 throw new IllegalArgumentException("Invalid band type: " + band); 1769 } 1770 mChannels = new SparseIntArray(1); 1771 mChannels.put(band, 0); 1772 return this; 1773 } 1774 1775 /** 1776 * Specifies the bands for the APs. 1777 * If more than 1 band is set, this will bring up concurrent APs. 1778 * on the requested bands (if possible). 1779 * <p> 1780 * 1781 * Use {@link WifiManager#isBridgedApConcurrencySupported()} to determine 1782 * whether or not concurrent APs are supported. 1783 * 1784 * Requires the driver to support {@link SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD} 1785 * when multiple bands are configured. Otherwise, 1786 * {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} will report error code 1787 * {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}. 1788 * 1789 * Note: Only supports 2.4GHz + 5GHz bands. If any other band is set, will report error 1790 * {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}. 1791 * 1792 * @param bands Array of the {@link #BandType}. 1793 * @return Builder for chaining. 1794 * @throws IllegalArgumentException when more than 2 bands are set or an invalid band type 1795 * is provided. 1796 * 1797 * @hide 1798 */ 1799 @RequiresApi(Build.VERSION_CODES.S) 1800 @NonNull 1801 @SystemApi setBands(@onNull int[] bands)1802 public Builder setBands(@NonNull int[] bands) { 1803 if (!SdkLevel.isAtLeastS()) { 1804 throw new UnsupportedOperationException(); 1805 } 1806 if (bands.length == 0 || bands.length > 2) { 1807 throw new IllegalArgumentException("Unsupported number of bands(" 1808 + bands.length + ") configured"); 1809 } 1810 SparseIntArray channels = new SparseIntArray(bands.length); 1811 for (int val : bands) { 1812 if (!isBandValid(val)) { 1813 throw new IllegalArgumentException("Invalid band type: " + val); 1814 } 1815 channels.put(val, 0); 1816 } 1817 mChannels = channels; 1818 return this; 1819 } 1820 1821 1822 /** 1823 * Specifies the channel and associated band for the AP. 1824 * 1825 * The channel which AP resides on. Valid channels are country dependent. 1826 * The {@link SoftApCapability#getSupportedChannelList(int)} can be used to obtain 1827 * valid channels. 1828 * 1829 * <p> 1830 * If not set, the default for the channel is the special value 0 which has the 1831 * framework auto-select a valid channel from the band configured with 1832 * {@link #setBand(int)}. 1833 * 1834 * The channel auto selection will be offloaded to driver when 1835 * {@link SoftApCapability#areFeaturesSupported(long)} 1836 * with {@link SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD} 1837 * return true. The driver will auto select the best channel (e.g. best performance) 1838 * based on environment interference. Check {@link SoftApCapability} for more detail. 1839 * 1840 * The API contains (band, channel) input since the 6GHz band uses the same channel 1841 * numbering scheme as is used in the 2.4GHz and 5GHz band. Therefore, both are needed to 1842 * uniquely identify individual channels. 1843 * 1844 * <p> 1845 * @param channel operating channel of the AP. 1846 * @param band containing this channel. 1847 * @return Builder for chaining. 1848 * @throws IllegalArgumentException when the invalid channel or band type is configured. 1849 * 1850 * @hide 1851 */ 1852 @NonNull 1853 @SystemApi setChannel(int channel, @BandType int band)1854 public Builder setChannel(int channel, @BandType int band) { 1855 if (!isChannelBandPairValid(channel, band)) { 1856 throw new IllegalArgumentException("Invalid channel(" + channel 1857 + ") & band (" + band + ") configured"); 1858 } 1859 mChannels = new SparseIntArray(1); 1860 mChannels.put(band, channel); 1861 return this; 1862 } 1863 1864 /** 1865 * Specifies the channels and associated bands for the APs. 1866 * <p> 1867 * The API contains (band, channel) input since the 6GHz band uses the same channel 1868 * numbering scheme as is used in the 2.4GHz and 5GHz band. Therefore, both are needed to 1869 * uniquely identify individual channels. 1870 * <p> 1871 * Reference the Wi-Fi channel numbering and the channelization in IEEE 802.11-2016 1872 * specifications, section 17.3.8.4.2, 17.3.8.4.3 and Table 15-6. 1873 * <p> 1874 * Using the special value 0 which has the framework auto-select a valid channel 1875 * from the band configured. 1876 * When more than 1 channel/band is set, this will bring up concurrent APs on the requested 1877 * channels and bands (if possible). 1878 * Use {@link WifiManager#isBridgedApConcurrencySupported()} to determine 1879 * whether concurrent APs are supported. 1880 * If not set, the default value is {@link #BAND_2GHZ} with the special channel value 0 1881 * which has the framework auto-select from {@link #BAND_2GHZ}. 1882 * 1883 * <p> 1884 * @param channels SparseIntArray (key: {@code #BandType} , value: channel) consists of 1885 * {@code BAND_} and corresponding channel. 1886 * @return Builder for chaining. 1887 * @throws IllegalArgumentException when more than 2 channels are set or the invalid 1888 * channel or band type is configured. 1889 */ 1890 @RequiresApi(Build.VERSION_CODES.S) 1891 @NonNull setChannels(@onNull SparseIntArray channels)1892 public Builder setChannels(@NonNull SparseIntArray channels) { 1893 if (!SdkLevel.isAtLeastS()) { 1894 throw new UnsupportedOperationException(); 1895 } 1896 if (channels.size() == 0 || channels.size() > 2) { 1897 throw new IllegalArgumentException("Unsupported number of channels(" 1898 + channels.size() + ") configured"); 1899 } 1900 for (int i = 0; i < channels.size(); i++) { 1901 int channel = channels.valueAt(i); 1902 int band = channels.keyAt(i); 1903 if (channel == 0) { 1904 if (!isBandValid(band)) { 1905 throw new IllegalArgumentException("Invalid band type: " + band); 1906 } 1907 } else { 1908 if (!isChannelBandPairValid(channel, band)) { 1909 throw new IllegalArgumentException("Invalid channel(" + channel 1910 + ") & band (" + band + ") configured"); 1911 } 1912 } 1913 } 1914 mChannels = channels.clone(); 1915 return this; 1916 } 1917 1918 1919 /** 1920 * Specifies the maximum number of clients that can associate to the AP. 1921 * 1922 * The maximum number of clients (STAs) which can associate to the AP. 1923 * The AP will reject association from any clients above this number. 1924 * Specify a value of 0 to have the framework automatically use the maximum number 1925 * which the device can support (based on hardware and carrier constraints). 1926 * <p> 1927 * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and 1928 * {@link SoftApCapability#getMaxSupportedClients} to get the maximum number of clients 1929 * which the device supports (based on hardware and carrier constraints). 1930 * 1931 * <p> 1932 * <li>If not set, defaults to 0.</li> 1933 * 1934 * This method requires HAL support. If the method is used to set a 1935 * non-zero {@code maxNumberOfClients} value then 1936 * {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} will report error code 1937 * {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}. 1938 * 1939 * <p> 1940 * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and 1941 * {@link SoftApCapability#areFeaturesSupported(long)} 1942 * with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} to determine whether 1943 * or not this feature is supported. 1944 * 1945 * @param maxNumberOfClients maximum client number of the AP. 1946 * @return Builder for chaining. 1947 * 1948 * @hide 1949 */ 1950 @NonNull 1951 @SystemApi setMaxNumberOfClients(@ntRangefrom = 0) int maxNumberOfClients)1952 public Builder setMaxNumberOfClients(@IntRange(from = 0) int maxNumberOfClients) { 1953 if (maxNumberOfClients < 0) { 1954 throw new IllegalArgumentException("maxNumberOfClients should be not negative"); 1955 } 1956 mMaxNumberOfClients = maxNumberOfClients; 1957 return this; 1958 } 1959 1960 /** 1961 * Specifies whether auto shutdown is enabled or not. 1962 * The Soft AP will shut down when there are no devices connected to it for 1963 * the timeout duration. 1964 * 1965 * <p> 1966 * <li>If not set, defaults to true</li> 1967 * 1968 * @param enable true to enable, false to disable. 1969 * @return Builder for chaining. 1970 * 1971 * @see #setShutdownTimeoutMillis(long) 1972 * 1973 * @hide 1974 */ 1975 @NonNull 1976 @SystemApi setAutoShutdownEnabled(boolean enable)1977 public Builder setAutoShutdownEnabled(boolean enable) { 1978 mAutoShutdownEnabled = enable; 1979 return this; 1980 } 1981 1982 /** 1983 * Specifies the shutdown timeout in milliseconds. 1984 * The Soft AP will shut down when there are no devices connected to it for 1985 * the timeout duration. 1986 * 1987 * Specify a value of {@link #DEFAULT_TIMEOUT} to have the framework automatically use 1988 * default timeout setting which defined in 1989 * {@link R.integer.config_wifi_framework_soft_ap_timeout_delay} 1990 * 1991 * <p> 1992 * <li>If not set, defaults to {@link #DEFAULT_TIMEOUT}</li> 1993 * <li>The shut down timeout will apply when {@link #setAutoShutdownEnabled(boolean)} is 1994 * set to true</li> 1995 * 1996 * @param timeoutMillis milliseconds of the timeout delay. Any value less than 1 is invalid 1997 * except {@link #DEFAULT_TIMEOUT}. 1998 * @return Builder for chaining. 1999 * 2000 * @see #setAutoShutdownEnabled(boolean) 2001 * 2002 * @hide 2003 */ 2004 @NonNull 2005 @SystemApi setShutdownTimeoutMillis(@ntRangefrom = -1) long timeoutMillis)2006 public Builder setShutdownTimeoutMillis(@IntRange(from = -1) long timeoutMillis) { 2007 if (CompatChanges.isChangeEnabled( 2008 REMOVE_ZERO_FOR_TIMEOUT_SETTING) && timeoutMillis < 1) { 2009 if (timeoutMillis != DEFAULT_TIMEOUT) { 2010 throw new IllegalArgumentException("Invalid timeout value: " + timeoutMillis); 2011 } 2012 } else if (timeoutMillis < 0) { 2013 throw new IllegalArgumentException("Invalid timeout value from legacy app: " 2014 + timeoutMillis); 2015 } 2016 mShutdownTimeoutMillis = timeoutMillis; 2017 return this; 2018 } 2019 2020 /** 2021 * Configure the Soft AP to require manual user control of client association. 2022 * If disabled (the default) then any client which isn't in the blocked list 2023 * {@link #getBlockedClientList()} can associate to this Soft AP using the 2024 * correct credentials until the Soft AP capacity is reached (capacity is hardware, carrier, 2025 * or user limited - using {@link #setMaxNumberOfClients(int)}). 2026 * 2027 * If manual user control is enabled then clients will be accepted, rejected, or require 2028 * a user approval based on the configuration provided by 2029 * {@link #setBlockedClientList(List)} and {@link #setAllowedClientList(List)}. 2030 * 2031 * <p> 2032 * This method requires HAL support. HAL support can be determined using 2033 * {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and 2034 * {@link SoftApCapability#areFeaturesSupported(long)} 2035 * with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} 2036 * 2037 * <p> 2038 * If the method is called on a device without HAL support then starting the soft AP 2039 * using {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} will fail with 2040 * {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}. 2041 * 2042 * <p> 2043 * <li>If not set, defaults to false (i.e The authoriztion is not required).</li> 2044 * 2045 * @param enabled true for enabling the control by user, false otherwise. 2046 * @return Builder for chaining. 2047 * 2048 * @hide 2049 */ 2050 @NonNull 2051 @SystemApi setClientControlByUserEnabled(boolean enabled)2052 public Builder setClientControlByUserEnabled(boolean enabled) { 2053 mClientControlByUser = enabled; 2054 return this; 2055 } 2056 2057 /** 2058 * Configures the set of channel numbers in the specified band that are allowed 2059 * to be selected by the Automatic Channel Selection (ACS) algorithm. 2060 * <p> 2061 * 2062 * Requires the driver to support {@link SoftApCapability#SOFTAP_FEATURE_ACS_OFFLOAD}. 2063 * Otherwise, these sets will be ignored. 2064 * <p> 2065 * 2066 * @param band one of the following band types: 2067 * {@link #BAND_2GHZ}, {@link #BAND_5GHZ}, {@link #BAND_6GHZ}. 2068 * 2069 * @param channels that are allowed to be used by ACS algorithm in this band. If it is 2070 * configured to an empty array or not configured, then all channels within that band 2071 * will be allowed. 2072 * <p> 2073 * 2074 * @return Builder for chaining. 2075 * 2076 * @hide 2077 */ 2078 @NonNull 2079 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2080 @SystemApi setAllowedAcsChannels(@andType int band, @NonNull int[] channels)2081 public Builder setAllowedAcsChannels(@BandType int band, @NonNull int[] channels) { 2082 if (!SdkLevel.isAtLeastT()) { 2083 throw new UnsupportedOperationException(); 2084 } 2085 2086 if (channels == null) { 2087 throw new IllegalArgumentException( 2088 "Passing a null object to setAllowedAcsChannels"); 2089 } 2090 2091 if ((band != BAND_2GHZ) && (band != BAND_5GHZ) && (band != BAND_6GHZ)) { 2092 throw new IllegalArgumentException( 2093 "Passing an invalid band to setAllowedAcsChannels"); 2094 } 2095 2096 for (int channel : channels) { 2097 if (!isChannelBandPairValid(channel, band)) { 2098 throw new IllegalArgumentException( 2099 "Invalid channel to setAllowedAcsChannels: band: " + band 2100 + "channel: " + channel); 2101 } 2102 } 2103 2104 HashSet<Integer> set = IntStream.of(channels).boxed() 2105 .collect(Collectors.toCollection(HashSet::new)); 2106 switch(band) { 2107 case BAND_2GHZ: 2108 mAllowedAcsChannels2g = set; 2109 break; 2110 case BAND_5GHZ: 2111 mAllowedAcsChannels5g = set; 2112 break; 2113 case BAND_6GHZ: 2114 mAllowedAcsChannels6g = set; 2115 break; 2116 } 2117 2118 return this; 2119 } 2120 2121 /** 2122 * Sets maximum channel bandwidth for the SoftAp Connection 2123 * 2124 * If not set, the SoftAp connection will seek the maximum channel bandwidth achievable on 2125 * the device. However, in some cases the caller will need to put a cap on the channel 2126 * bandwidth through this API. 2127 * 2128 * @param maxChannelBandwidth one of {@link SoftApInfo#CHANNEL_WIDTH_AUTO}, 2129 * {@link SoftApInfo#CHANNEL_WIDTH_20MHZ}, {@link SoftApInfo#CHANNEL_WIDTH_40MHZ}, 2130 * {@link SoftApInfo#CHANNEL_WIDTH_80MHZ}, {@link SoftApInfo#CHANNEL_WIDTH_160MHZ}, 2131 * or {@link SoftApInfo#CHANNEL_WIDTH_320MHZ} 2132 * 2133 * @return builder for chaining 2134 * 2135 * @hide 2136 */ 2137 @NonNull 2138 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2139 @SystemApi setMaxChannelBandwidth(@ifiAnnotations.Bandwidth int maxChannelBandwidth)2140 public Builder setMaxChannelBandwidth(@WifiAnnotations.Bandwidth int maxChannelBandwidth) { 2141 if (!SdkLevel.isAtLeastT()) { 2142 throw new UnsupportedOperationException(); 2143 } 2144 2145 switch (maxChannelBandwidth) { 2146 case SoftApInfo.CHANNEL_WIDTH_AUTO: 2147 case SoftApInfo.CHANNEL_WIDTH_20MHZ: 2148 case SoftApInfo.CHANNEL_WIDTH_40MHZ: 2149 case SoftApInfo.CHANNEL_WIDTH_80MHZ: 2150 case SoftApInfo.CHANNEL_WIDTH_160MHZ: 2151 case SoftApInfo.CHANNEL_WIDTH_320MHZ: 2152 mMaxChannelBandwidth = maxChannelBandwidth; 2153 break; 2154 default: 2155 throw new IllegalArgumentException( 2156 "Invalid channel bandwidth value(" 2157 + maxChannelBandwidth + ") configured"); 2158 } 2159 return this; 2160 } 2161 2162 /** 2163 * This method together with {@link setClientControlByUserEnabled(boolean)} control client 2164 * connections to the AP. If client control by user is disabled using the above method then 2165 * this API has no effect and clients are allowed to associate to the AP (within limit of 2166 * max number of clients). 2167 * 2168 * If client control by user is enabled then this API configures the list of clients 2169 * which are explicitly allowed. These are auto-accepted. 2170 * 2171 * All other clients which attempt to associate, whose MAC addresses are on neither list, 2172 * are: 2173 * <ul> 2174 * <li>Rejected</li> 2175 * <li>A callback {@link WifiManager.SoftApCallback#onBlockedClientConnecting(WifiClient)} 2176 * is issued (which allows the user to add them to the allowed client list if desired).<li> 2177 * </ul> 2178 * 2179 * @param allowedClientList list of clients which are allowed to associate to the AP 2180 * without user pre-approval. 2181 * @return Builder for chaining. 2182 * 2183 * @hide 2184 */ 2185 @NonNull 2186 @SystemApi setAllowedClientList(@onNull List<MacAddress> allowedClientList)2187 public Builder setAllowedClientList(@NonNull List<MacAddress> allowedClientList) { 2188 mAllowedClientList = new ArrayList<>(allowedClientList); 2189 return this; 2190 } 2191 2192 /** 2193 * This API configures the list of clients which are blocked and cannot associate 2194 * to the Soft AP. 2195 * 2196 * <p> 2197 * This method requires HAL support. HAL support can be determined using 2198 * {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and 2199 * {@link SoftApCapability#areFeaturesSupported(long)} 2200 * with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} 2201 * 2202 * <p> 2203 * If the method is called on a device without HAL support then starting the soft AP 2204 * using {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} will fail with 2205 * {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}. 2206 * 2207 * @param blockedClientList list of clients which are not allowed to associate to the AP. 2208 * @return Builder for chaining. 2209 * 2210 * @hide 2211 */ 2212 @NonNull 2213 @SystemApi setBlockedClientList(@onNull List<MacAddress> blockedClientList)2214 public Builder setBlockedClientList(@NonNull List<MacAddress> blockedClientList) { 2215 mBlockedClientList = new ArrayList<>(blockedClientList); 2216 return this; 2217 } 2218 2219 /** 2220 * Specifies the level of MAC randomization for the AP BSSID. 2221 * The Soft AP BSSID will be randomized only if the BSSID isn't set 2222 * {@link #setBssid(MacAddress)} and this method is either uncalled 2223 * or called with {@link #RANDOMIZATION_PERSISTENT} or 2224 * {@link #RANDOMIZATION_NON_PERSISTENT}. When this method is called with 2225 * {@link #RANDOMIZATION_PERSISTENT} or {@link #RANDOMIZATION_NON_PERSISTENT}, the caller 2226 * the caller must not call {@link #setBssid(MacAddress)}. 2227 * 2228 * <p> 2229 * <li>If not set, defaults to {@link #RANDOMIZATION_NON_PERSISTENT}</li> 2230 * 2231 * <p> 2232 * Requires HAL support when set to {@link #RANDOMIZATION_PERSISTENT} or 2233 * {@link #RANDOMIZATION_NON_PERSISTENT}. 2234 * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and 2235 * {@link SoftApCapability#areFeaturesSupported(long)} 2236 * with {@link SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION} to determine 2237 * whether or not this feature is supported. 2238 * 2239 * @param macRandomizationSetting One of the following setting: 2240 * {@link #RANDOMIZATION_NONE}, {@link #RANDOMIZATION_PERSISTENT} or 2241 * {@link #RANDOMIZATION_NON_PERSISTENT}. 2242 * @return Builder for chaining. 2243 * 2244 * @see #setBssid(MacAddress) 2245 * 2246 * @hide 2247 */ 2248 @RequiresApi(Build.VERSION_CODES.S) 2249 @NonNull 2250 @SystemApi setMacRandomizationSetting( @acRandomizationSetting int macRandomizationSetting)2251 public Builder setMacRandomizationSetting( 2252 @MacRandomizationSetting int macRandomizationSetting) { 2253 if (!SdkLevel.isAtLeastS()) { 2254 throw new UnsupportedOperationException(); 2255 } 2256 mMacRandomizationSetting = macRandomizationSetting; 2257 return this; 2258 } 2259 2260 2261 /** 2262 * Specifies whether or not opportunistic shut down of an AP instance in bridged mode 2263 * is enabled. 2264 * 2265 * <p> 2266 * If enabled, the framework will shutdown one of the AP instances if it is idle for 2267 * the timeout duration - meaning there are no devices connected to it. 2268 * If both AP instances are idle for the timeout duration then the framework will 2269 * shut down the AP instance operating on the higher frequency. For instance, 2270 * if the AP instances operate at 2.4GHz and 5GHz and are both idle for the 2271 * timeout duration then the 5GHz AP instance will be shut down. 2272 * <p> 2273 * 2274 * Note: the opportunistic timeout only applies to one AP instance of the bridge AP. 2275 * If one of the AP instances has already been disabled for any reason, including due to 2276 * an opportunistic timeout or hardware issues or coexistence issues, 2277 * then the opportunistic timeout is no longer active. 2278 * 2279 * <p> 2280 * The shutdown timer specified by {@link #setShutdownTimeoutMillis(long)} controls the 2281 * overall shutdown of the bridged AP and is still in use independently of the opportunistic 2282 * timer controlled by this AP. 2283 * 2284 * <p> 2285 * <li>If not set, defaults to true</li> 2286 * 2287 * @param enable true to enable, false to disable. 2288 * @return Builder for chaining. 2289 * 2290 * @hide 2291 */ 2292 @RequiresApi(Build.VERSION_CODES.S) 2293 @NonNull 2294 @SystemApi setBridgedModeOpportunisticShutdownEnabled(boolean enable)2295 public Builder setBridgedModeOpportunisticShutdownEnabled(boolean enable) { 2296 if (!SdkLevel.isAtLeastS()) { 2297 throw new UnsupportedOperationException(); 2298 } 2299 mBridgedModeOpportunisticShutdownEnabled = enable; 2300 return this; 2301 } 2302 2303 /** 2304 * Specifies whether or not to enable 802.11ax on the Soft AP. 2305 * 2306 * <p> 2307 * Note: Only relevant when the device supports 802.11ax on the Soft AP. 2308 * If enabled on devices that do not support 802.11ax then ignored. 2309 * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and 2310 * {@link SoftApCapability#areFeaturesSupported(long)} 2311 * with {@link SoftApCapability.SOFTAP_FEATURE_IEEE80211_AX} to determine 2312 * whether or not 802.11ax is supported on the Soft AP. 2313 * <p> 2314 * <li>If not set, defaults to true - which will be ignored on devices 2315 * which do not support 802.11ax</li> 2316 * 2317 * @param enable true to enable, false to disable. 2318 * @return Builder for chaining. 2319 * 2320 * @hide 2321 */ 2322 @RequiresApi(Build.VERSION_CODES.S) 2323 @NonNull 2324 @SystemApi setIeee80211axEnabled(boolean enable)2325 public Builder setIeee80211axEnabled(boolean enable) { 2326 if (!SdkLevel.isAtLeastS()) { 2327 throw new UnsupportedOperationException(); 2328 } 2329 mIeee80211axEnabled = enable; 2330 return this; 2331 } 2332 2333 /** 2334 * Specifies whether or not to enable 802.11be on the Soft AP. 2335 * 2336 * <p> 2337 * Note: Only relevant when the device supports 802.11be on the Soft AP. 2338 * If enabled on devices that do not support 802.11be then ignored. 2339 * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and 2340 * {@link SoftApCapability#areFeaturesSupported(long)} 2341 * with {@link SoftApCapability.SOFTAP_FEATURE_IEEE80211_BE} to determine 2342 * whether or not 802.11be is supported on the Soft AP. 2343 * <p> 2344 * <li>If not set, defaults to true - which will be ignored on devices 2345 * which do not support 802.11be</li> 2346 * 2347 * @param enable true to enable, false to disable. 2348 * @return Builder for chaining. 2349 * 2350 * @hide 2351 */ 2352 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2353 @NonNull 2354 @SystemApi setIeee80211beEnabled(boolean enable)2355 public Builder setIeee80211beEnabled(boolean enable) { 2356 if (!SdkLevel.isAtLeastT()) { 2357 throw new UnsupportedOperationException(); 2358 } 2359 mIeee80211beEnabled = enable; 2360 return this; 2361 } 2362 2363 /** 2364 * Specifies whether or not the configuration is configured by user. 2365 * 2366 * @param isUserConfigured true to user configuration, false otherwise. 2367 * @return Builder for chaining. 2368 * 2369 * @hide 2370 */ 2371 @NonNull setUserConfiguration(boolean isUserConfigured)2372 public Builder setUserConfiguration(boolean isUserConfigured) { 2373 mIsUserConfiguration = isUserConfigured; 2374 return this; 2375 } 2376 2377 /** 2378 * Specifies bridged mode opportunistic shutdown timeout in milliseconds. 2379 * An instance of bridged Soft AP will shut down when there is no device connected to it 2380 * for this timeout duration. 2381 * 2382 * Specify a value of {@link DEFAULT_TIMEOUT} to have the framework automatically use 2383 * default timeout setting defined by 2384 * {@link 2385 * R.integer.config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond} 2386 * 2387 * <p> 2388 * <li>If not set, defaults to {@link #DEFAULT_TIMEOUT}</li> 2389 * <li>The shut down timeout will apply when 2390 * {@link #setBridgedModeOpportunisticShutdownEnabled(boolean)} is set to true</li> 2391 * 2392 * @param timeoutMillis milliseconds of the timeout delay. Any value less than 1 is invalid 2393 * except {@link #DEFAULT_TIMEOUT}. 2394 * @return Builder for chaining. 2395 * 2396 * @see #setBridgedModeOpportunisticShutdownEnabled(boolean) 2397 * 2398 * @hide 2399 */ 2400 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 2401 @NonNull 2402 @SystemApi setBridgedModeOpportunisticShutdownTimeoutMillis( @ntRangefrom = -1) long timeoutMillis)2403 public Builder setBridgedModeOpportunisticShutdownTimeoutMillis( 2404 @IntRange(from = -1) long timeoutMillis) { 2405 if (!SdkLevel.isAtLeastT()) { 2406 throw new UnsupportedOperationException(); 2407 } 2408 if (timeoutMillis < 1 && timeoutMillis != DEFAULT_TIMEOUT) { 2409 throw new IllegalArgumentException("Invalid timeout value: " + timeoutMillis); 2410 } 2411 mBridgedModeOpportunisticShutdownTimeoutMillis = timeoutMillis; 2412 return this; 2413 } 2414 2415 /** 2416 * @param mac persistent randomized MacAddress generated by the frameworks. 2417 * @hide 2418 */ 2419 @NonNull setRandomizedMacAddress(@onNull MacAddress mac)2420 public Builder setRandomizedMacAddress(@NonNull MacAddress mac) { 2421 if (mac == null) { 2422 throw new IllegalArgumentException("setRandomizedMacAddress received" 2423 + " null MacAddress."); 2424 } 2425 mPersistentRandomizedMacAddress = mac; 2426 return this; 2427 } 2428 2429 /** 2430 * Set additional vendor-provided configuration data. 2431 * 2432 * @param vendorData List of {@link OuiKeyedData} containing the vendor-provided 2433 * configuration data. Note that multiple elements with the same OUI are allowed. 2434 * @return Builder for chaining. 2435 * 2436 * @hide 2437 */ 2438 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 2439 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) 2440 @NonNull 2441 @SystemApi setVendorData(@onNull List<OuiKeyedData> vendorData)2442 public Builder setVendorData(@NonNull List<OuiKeyedData> vendorData) { 2443 if (!SdkLevel.isAtLeastV()) { 2444 throw new UnsupportedOperationException(); 2445 } 2446 if (vendorData == null) { 2447 throw new IllegalArgumentException("setVendorData received a null value"); 2448 } 2449 mVendorData = vendorData; 2450 return this; 2451 } 2452 2453 /** 2454 * Specifies whether or not client isolation is enabled. 2455 * 2456 * Client isolation can be used to disallow a connected Soft AP 2457 * client to communicate with other connected clients. 2458 * 2459 * @param isClientIsolationEnabled true when enabling client isolation. 2460 * @return Builder for chaining. 2461 * 2462 * @hide 2463 */ 2464 @FlaggedApi(Flags.FLAG_AP_ISOLATE) 2465 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 2466 @NonNull 2467 @SystemApi setClientIsolationEnabled(boolean isClientIsolationEnabled)2468 public Builder setClientIsolationEnabled(boolean isClientIsolationEnabled) { 2469 if (!Environment.isSdkAtLeastB()) { 2470 throw new UnsupportedOperationException(); 2471 } 2472 mIsClientIsolationEnabled = isClientIsolationEnabled; 2473 return this; 2474 } 2475 } 2476 } 2477