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.LongDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.net.MacAddress; 24 import android.net.wifi.SoftApConfiguration.BandType; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 28 import java.lang.annotation.Retention; 29 import java.lang.annotation.RetentionPolicy; 30 import java.util.Arrays; 31 import java.util.Objects; 32 33 /** 34 * A class representing capability of the SoftAp. 35 * {@see WifiManager} 36 * 37 * @hide 38 */ 39 @SystemApi 40 public final class SoftApCapability implements Parcelable { 41 42 private static final String TAG = "SoftApCapability"; 43 private static final int[] EMPTY_INT_ARRAY = new int[0]; 44 /** 45 * Support for automatic channel selection in driver (ACS). 46 * Driver will auto select best channel based on interference to optimize performance. 47 * 48 * flag when {@code R.bool.config_wifi_softap_acs_supported} is true. 49 * 50 * <p> 51 * Use {@link WifiManager.SoftApCallback#onInfoChanged(SoftApInfo)} and 52 * {@link SoftApInfo#getFrequency()} and {@link SoftApInfo#getBandwidth()} to get 53 * driver channel selection result. 54 */ 55 public static final long SOFTAP_FEATURE_ACS_OFFLOAD = 1 << 0; 56 57 /** 58 * Support for client force disconnect. 59 * flag when {@code R.bool.config_wifiSofapClientForceDisconnectSupported} is true 60 * 61 * <p> 62 * Several Soft AP client control features, e.g. specifying the maximum number of 63 * Soft AP clients, only work when this feature support is present. 64 * Check feature support before invoking 65 * {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)} 66 */ 67 public static final long SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 1 << 1; 68 69 /** 70 * Support for WPA3 Simultaneous Authentication of Equals (WPA3-SAE). 71 * 72 * flag when {@code config_wifi_softap_sae_supported} is true. 73 */ 74 public static final long SOFTAP_FEATURE_WPA3_SAE = 1 << 2; 75 76 /** 77 * Support for MAC address customization. 78 * flag when {@code R.bool.config_wifiSoftapMacAddressCustomizationSupported} is true 79 * 80 * <p> 81 * Check feature support before invoking 82 * {@link SoftApConfiguration.Builder#setBssid(MacAddress)} or 83 * {@link SoftApConfiguration.Builder#setMacRandomizationSetting(int)} with 84 * {@link SoftApConfiguration#RANDOMIZATION_PERSISTENT} 85 */ 86 public static final long SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION = 1 << 3; 87 88 /** 89 * Support for 802.11ax SAP. 90 * flag when {@code R.bool.config_wifiSoftapIeee80211axSupported} is true 91 * 92 * <p> 93 * Check feature support before invoking 94 * {@link SoftApConfiguration.Builder#setIeee80211axEnabled(boolean)} 95 */ 96 public static final long SOFTAP_FEATURE_IEEE80211_AX = 1 << 4; 97 98 /** 99 * Support for 2.4G Band. 100 * flag when {@code R.bool.config_wifiSoftap24ghzSupported} is true 101 */ 102 public static final long SOFTAP_FEATURE_BAND_24G_SUPPORTED = 1 << 5; 103 104 /** 105 * Support for 5G Band. 106 * flag when {@code R.bool.config_wifiSoftap5ghzSupported} is true 107 */ 108 public static final long SOFTAP_FEATURE_BAND_5G_SUPPORTED = 1 << 6; 109 110 /** 111 * Support for 6G Band. 112 * flag when {@code R.bool.config_wifiSoftap6ghzSupported} is true 113 */ 114 public static final long SOFTAP_FEATURE_BAND_6G_SUPPORTED = 1 << 7; 115 116 /** 117 * Support for 60G Band. 118 * flag when {@code R.bool.config_wifiSoftap60ghzSupported} is true 119 */ 120 public static final long SOFTAP_FEATURE_BAND_60G_SUPPORTED = 1 << 8; 121 122 /** 123 * Support for 802.11be SAP. 124 * flag when {@code R.bool.config_wifiSoftapIeee80211beSupported} is true 125 * 126 * <p> 127 * Use this flag with {@link #areFeaturesSupported(long)} 128 * to verify that 802.11be is supported before enabling it using 129 * {@link SoftApConfiguration.Builder#setIeee80211beEnabled(boolean)} 130 */ 131 public static final long SOFTAP_FEATURE_IEEE80211_BE = 1 << 9; 132 133 /* 134 * Support for WPA3-Opportunistic Wireless Encryption (OWE) transition. 135 * flag when {@code R.bool.config_wifiSoftapOweTransitionSupported} is true. 136 */ 137 public static final long SOFTAP_FEATURE_WPA3_OWE_TRANSITION = 1 << 10; 138 139 /* 140 * Support for WPA3-Opportunistic Wireless Encryption (OWE). 141 * flag when {@code R.bool.config_wifiSoftapOweSupported} is true. 142 */ 143 public static final long SOFTAP_FEATURE_WPA3_OWE = 1 << 11; 144 145 /** @hide */ 146 @Retention(RetentionPolicy.SOURCE) 147 @LongDef(flag = true, prefix = { "SOFTAP_FEATURE_" }, value = { 148 SOFTAP_FEATURE_ACS_OFFLOAD, 149 SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT, 150 SOFTAP_FEATURE_WPA3_SAE, 151 SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION, 152 SOFTAP_FEATURE_IEEE80211_AX, 153 SOFTAP_FEATURE_IEEE80211_BE, 154 SOFTAP_FEATURE_BAND_24G_SUPPORTED, 155 SOFTAP_FEATURE_BAND_5G_SUPPORTED, 156 SOFTAP_FEATURE_BAND_6G_SUPPORTED, 157 SOFTAP_FEATURE_BAND_60G_SUPPORTED, 158 SOFTAP_FEATURE_WPA3_OWE_TRANSITION, 159 SOFTAP_FEATURE_WPA3_OWE, 160 }) 161 public @interface HotspotFeatures {} 162 163 private @HotspotFeatures long mSupportedFeatures = 0; 164 165 private int mMaximumSupportedClientNumber; 166 167 /** 168 * A list storing supported 2.4G channels. 169 */ 170 private int[] mSupportedChannelListIn24g = EMPTY_INT_ARRAY; 171 172 /** 173 * A list storing supported 5G channels. 174 */ 175 private int[] mSupportedChannelListIn5g = EMPTY_INT_ARRAY; 176 177 /** 178 * A list storing supported 6G channels. 179 */ 180 private int[] mSupportedChannelListIn6g = EMPTY_INT_ARRAY; 181 182 /** 183 * A list storing supported 60G channels. 184 */ 185 private int[] mSupportedChannelListIn60g = EMPTY_INT_ARRAY; 186 187 /** 188 * A base country code which is used when querying the supported channel list. 189 */ 190 private String mCountryCodeFromDriver; 191 192 /** 193 * Set the country code which is used when querying the supported channel list. 194 * @hide 195 */ setCountryCode(String countryCode)196 public void setCountryCode(String countryCode) { 197 mCountryCodeFromDriver = countryCode; 198 } 199 200 /** 201 * Get the country code which is used when querying the supported channel list. 202 * @hide 203 */ getCountryCode()204 public String getCountryCode() { 205 return mCountryCodeFromDriver; 206 } 207 208 /** 209 * Get the maximum supported client numbers which AP resides on. 210 */ getMaxSupportedClients()211 public int getMaxSupportedClients() { 212 return mMaximumSupportedClientNumber; 213 } 214 215 /** 216 * Set the maximum supported client numbers which AP resides on. 217 * 218 * @param maxClient maximum supported client numbers for the softap. 219 * @hide 220 */ setMaxSupportedClients(int maxClient)221 public void setMaxSupportedClients(int maxClient) { 222 mMaximumSupportedClientNumber = maxClient; 223 } 224 225 /** 226 * Returns true when all of the queried features are supported, otherwise false. 227 * 228 * @param features One or combination of {@code SOFTAP_FEATURE_}, for instance: 229 * {@link #SOFTAP_FEATURE_ACS_OFFLOAD}, {@link #SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} or 230 * {@link #SOFTAP_FEATURE_WPA3_SAE}. 231 */ areFeaturesSupported(@otspotFeatures long features)232 public boolean areFeaturesSupported(@HotspotFeatures long features) { 233 return (mSupportedFeatures & features) == features; 234 } 235 236 /** 237 * Set SoftAp Capabilities 238 * @param value Boolean to set value 0 or 1 239 * @param features @HotspotFeatures represents which feature to access 240 * @hide 241 */ setSupportedFeatures(boolean value, @HotspotFeatures long features)242 public void setSupportedFeatures(boolean value, @HotspotFeatures long features) { 243 if (value) { 244 mSupportedFeatures |= features; 245 } else { 246 mSupportedFeatures &= ~features; 247 } 248 } 249 250 /** 251 * Set supported channel list in target band type. 252 * 253 * @param band One of the following band types: 254 * {@link SoftApConfiguration#BAND_2GHZ}, {@link SoftApConfiguration#BAND_5GHZ}, 255 * {@link SoftApConfiguration#BAND_6GHZ}, or {@link SoftApConfiguration#BAND_60GHZ}. 256 * @param supportedChannelList supported channel list in target band 257 * @return true if band and supportedChannelList are valid, otherwise false. 258 * 259 * @throws IllegalArgumentException when band type is invalid. 260 * @hide 261 */ setSupportedChannelList(@andType int band, @Nullable int[] supportedChannelList)262 public boolean setSupportedChannelList(@BandType int band, 263 @Nullable int[] supportedChannelList) { 264 if (supportedChannelList == null) return false; 265 switch (band) { 266 case SoftApConfiguration.BAND_2GHZ: 267 mSupportedChannelListIn24g = supportedChannelList; 268 break; 269 case SoftApConfiguration.BAND_5GHZ: 270 mSupportedChannelListIn5g = supportedChannelList; 271 break; 272 case SoftApConfiguration.BAND_6GHZ: 273 mSupportedChannelListIn6g = supportedChannelList; 274 break; 275 case SoftApConfiguration.BAND_60GHZ: 276 mSupportedChannelListIn60g = supportedChannelList; 277 break; 278 default: 279 throw new IllegalArgumentException("Invalid band: " + band); 280 } 281 return true; 282 } 283 284 /** 285 * Returns a list of the supported channels in the given band. 286 * The result depends on the on the country code that has been set. 287 * Can be used to set the channel of the AP with the 288 * {@link SoftApConfiguration.Builder#setChannel(int, int)} API. 289 * 290 * @param band One of the following band types: 291 * {@link SoftApConfiguration#BAND_2GHZ}, {@link SoftApConfiguration#BAND_5GHZ}, 292 * {@link SoftApConfiguration#BAND_6GHZ}, {@link SoftApConfiguration#BAND_60GHZ}. 293 * @return List of supported channels for the band. An empty list will be returned if the 294 * channels are obsolete. This happens when country code has changed but the channels 295 * are not updated from HAL when Wifi is disabled. 296 * 297 * @throws IllegalArgumentException when band type is invalid. 298 */ 299 @NonNull getSupportedChannelList(@andType int band)300 public int[] getSupportedChannelList(@BandType int band) { 301 switch (band) { 302 case SoftApConfiguration.BAND_2GHZ: 303 return mSupportedChannelListIn24g; 304 case SoftApConfiguration.BAND_5GHZ: 305 return mSupportedChannelListIn5g; 306 case SoftApConfiguration.BAND_6GHZ: 307 return mSupportedChannelListIn6g; 308 case SoftApConfiguration.BAND_60GHZ: 309 return mSupportedChannelListIn60g; 310 default: 311 throw new IllegalArgumentException("Invalid band: " + band); 312 } 313 } 314 315 /** 316 * @hide 317 */ SoftApCapability(@ullable SoftApCapability source)318 public SoftApCapability(@Nullable SoftApCapability source) { 319 if (source != null) { 320 mSupportedFeatures = source.mSupportedFeatures; 321 mMaximumSupportedClientNumber = source.mMaximumSupportedClientNumber; 322 mSupportedChannelListIn24g = source.mSupportedChannelListIn24g; 323 mSupportedChannelListIn5g = source.mSupportedChannelListIn5g; 324 mSupportedChannelListIn6g = source.mSupportedChannelListIn6g; 325 mSupportedChannelListIn60g = source.mSupportedChannelListIn60g; 326 mCountryCodeFromDriver = source.mCountryCodeFromDriver; 327 } 328 } 329 330 /** 331 * Constructor with combination of the feature. 332 * Zero to no supported feature. 333 * 334 * @param features One or combination of {@code SOFTAP_FEATURE_}, for instance: 335 * {@link #SOFTAP_FEATURE_ACS_OFFLOAD}, {@link #SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} or 336 * {@link #SOFTAP_FEATURE_WPA3_SAE}. 337 * @hide 338 */ SoftApCapability(@otspotFeatures long features)339 public SoftApCapability(@HotspotFeatures long features) { 340 mSupportedFeatures = features; 341 } 342 343 @Override 344 /** Implement the Parcelable interface. */ describeContents()345 public int describeContents() { 346 return 0; 347 } 348 349 @Override 350 /** Implement the Parcelable interface */ writeToParcel(@onNull Parcel dest, int flags)351 public void writeToParcel(@NonNull Parcel dest, int flags) { 352 dest.writeLong(mSupportedFeatures); 353 dest.writeInt(mMaximumSupportedClientNumber); 354 dest.writeIntArray(mSupportedChannelListIn24g); 355 dest.writeIntArray(mSupportedChannelListIn5g); 356 dest.writeIntArray(mSupportedChannelListIn6g); 357 dest.writeIntArray(mSupportedChannelListIn60g); 358 dest.writeString(mCountryCodeFromDriver); 359 } 360 361 @NonNull 362 /** Implement the Parcelable interface */ 363 public static final Creator<SoftApCapability> CREATOR = new Creator<SoftApCapability>() { 364 public SoftApCapability createFromParcel(Parcel in) { 365 SoftApCapability capability = new SoftApCapability(in.readLong()); 366 capability.mMaximumSupportedClientNumber = in.readInt(); 367 capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, in.createIntArray()); 368 capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, in.createIntArray()); 369 capability.setSupportedChannelList(SoftApConfiguration.BAND_6GHZ, in.createIntArray()); 370 capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, in.createIntArray()); 371 capability.setCountryCode(in.readString()); 372 return capability; 373 } 374 375 public SoftApCapability[] newArray(int size) { 376 return new SoftApCapability[size]; 377 } 378 }; 379 380 @NonNull 381 @Override toString()382 public String toString() { 383 StringBuilder sbuf = new StringBuilder(); 384 sbuf.append("SupportedFeatures=").append(mSupportedFeatures); 385 sbuf.append(" MaximumSupportedClientNumber=").append(mMaximumSupportedClientNumber); 386 sbuf.append(" SupportedChannelListIn24g") 387 .append(Arrays.toString(mSupportedChannelListIn24g)); 388 sbuf.append(" SupportedChannelListIn5g").append(Arrays.toString(mSupportedChannelListIn5g)); 389 sbuf.append(" SupportedChannelListIn6g").append(Arrays.toString(mSupportedChannelListIn6g)); 390 sbuf.append(" SupportedChannelListIn60g") 391 .append(Arrays.toString(mSupportedChannelListIn60g)); 392 sbuf.append(" mCountryCodeFromDriver").append(mCountryCodeFromDriver); 393 return sbuf.toString(); 394 } 395 396 @Override equals(@ullable Object o)397 public boolean equals(@Nullable Object o) { 398 if (this == o) return true; 399 if (!(o instanceof SoftApCapability)) return false; 400 SoftApCapability capability = (SoftApCapability) o; 401 return mSupportedFeatures == capability.mSupportedFeatures 402 && mMaximumSupportedClientNumber == capability.mMaximumSupportedClientNumber 403 && Arrays.equals(mSupportedChannelListIn24g, capability.mSupportedChannelListIn24g) 404 && Arrays.equals(mSupportedChannelListIn5g, capability.mSupportedChannelListIn5g) 405 && Arrays.equals(mSupportedChannelListIn6g, capability.mSupportedChannelListIn6g) 406 && Arrays.equals(mSupportedChannelListIn60g, capability.mSupportedChannelListIn60g) 407 && Objects.equals(mCountryCodeFromDriver, capability.mCountryCodeFromDriver); 408 } 409 410 @Override hashCode()411 public int hashCode() { 412 return Objects.hash(mSupportedFeatures, mMaximumSupportedClientNumber, 413 Arrays.hashCode(mSupportedChannelListIn24g), 414 Arrays.hashCode(mSupportedChannelListIn5g), 415 Arrays.hashCode(mSupportedChannelListIn6g), 416 Arrays.hashCode(mSupportedChannelListIn60g), 417 mCountryCodeFromDriver); 418 } 419 } 420