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 /** @hide */ 123 @Retention(RetentionPolicy.SOURCE) 124 @LongDef(flag = true, prefix = { "SOFTAP_FEATURE_" }, value = { 125 SOFTAP_FEATURE_ACS_OFFLOAD, 126 SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT, 127 SOFTAP_FEATURE_WPA3_SAE, 128 SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION, 129 SOFTAP_FEATURE_IEEE80211_AX, 130 SOFTAP_FEATURE_BAND_24G_SUPPORTED, 131 SOFTAP_FEATURE_BAND_5G_SUPPORTED, 132 SOFTAP_FEATURE_BAND_6G_SUPPORTED, 133 SOFTAP_FEATURE_BAND_60G_SUPPORTED 134 }) 135 public @interface HotspotFeatures {} 136 137 private @HotspotFeatures long mSupportedFeatures = 0; 138 139 private int mMaximumSupportedClientNumber; 140 141 /** 142 * A list storing supported 2.4G channels. 143 */ 144 private int[] mSupportedChannelListIn24g = EMPTY_INT_ARRAY; 145 146 /** 147 * A list storing supported 5G channels. 148 */ 149 private int[] mSupportedChannelListIn5g = EMPTY_INT_ARRAY; 150 151 /** 152 * A list storing supported 6G channels. 153 */ 154 private int[] mSupportedChannelListIn6g = EMPTY_INT_ARRAY; 155 156 /** 157 * A list storing supported 60G channels. 158 */ 159 private int[] mSupportedChannelListIn60g = EMPTY_INT_ARRAY; 160 161 /** 162 * Get the maximum supported client numbers which AP resides on. 163 */ getMaxSupportedClients()164 public int getMaxSupportedClients() { 165 return mMaximumSupportedClientNumber; 166 } 167 168 /** 169 * Set the maximum supported client numbers which AP resides on. 170 * 171 * @param maxClient maximum supported client numbers for the softap. 172 * @hide 173 */ setMaxSupportedClients(int maxClient)174 public void setMaxSupportedClients(int maxClient) { 175 mMaximumSupportedClientNumber = maxClient; 176 } 177 178 /** 179 * Returns true when all of the queried features are supported, otherwise false. 180 * 181 * @param features One or combination of {@code SOFTAP_FEATURE_}, for instance: 182 * {@link #SOFTAP_FEATURE_ACS_OFFLOAD}, {@link #SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} or 183 * {@link #SOFTAP_FEATURE_WPA3_SAE}. 184 */ areFeaturesSupported(@otspotFeatures long features)185 public boolean areFeaturesSupported(@HotspotFeatures long features) { 186 return (mSupportedFeatures & features) == features; 187 } 188 189 /** 190 * Set supported channel list in target band type. 191 * 192 * @param band One of the following band types: 193 * {@link SoftApConfiguration#BAND_2GHZ}, {@link SoftApConfiguration#BAND_5GHZ}, 194 * {@link SoftApConfiguration#BAND_6GHZ}, or {@link SoftApConfiguration#BAND_60GHZ}. 195 * @param supportedChannelList supported channel list in target band 196 * @return true if band and supportedChannelList are valid, otherwise false. 197 * 198 * @throws IllegalArgumentException when band type is invalid. 199 * @hide 200 */ setSupportedChannelList(@andType int band, @Nullable int[] supportedChannelList)201 public boolean setSupportedChannelList(@BandType int band, 202 @Nullable int[] supportedChannelList) { 203 if (supportedChannelList == null) return false; 204 switch (band) { 205 case SoftApConfiguration.BAND_2GHZ: 206 mSupportedChannelListIn24g = supportedChannelList; 207 break; 208 case SoftApConfiguration.BAND_5GHZ: 209 mSupportedChannelListIn5g = supportedChannelList; 210 break; 211 case SoftApConfiguration.BAND_6GHZ: 212 mSupportedChannelListIn6g = supportedChannelList; 213 break; 214 case SoftApConfiguration.BAND_60GHZ: 215 mSupportedChannelListIn60g = supportedChannelList; 216 break; 217 default: 218 throw new IllegalArgumentException("Invalid band: " + band); 219 } 220 return true; 221 } 222 223 /** 224 * Returns a list of the supported channels in the given band. 225 * The result depends on the on the country code that has been set. 226 * Can be used to set the channel of the AP with the 227 * {@link SoftApConfiguration.Builder#setChannel(int, int)} API. 228 * 229 * @param band One of the following band types: 230 * {@link SoftApConfiguration#BAND_2GHZ}, {@link SoftApConfiguration#BAND_5GHZ}, 231 * {@link SoftApConfiguration#BAND_6GHZ}, {@link SoftApConfiguration#BAND_60GHZ}. 232 * @return List of supported channels for the band. 233 * 234 * @throws IllegalArgumentException when band type is invalid. 235 */ 236 @NonNull getSupportedChannelList(@andType int band)237 public int[] getSupportedChannelList(@BandType int band) { 238 switch (band) { 239 case SoftApConfiguration.BAND_2GHZ: 240 return mSupportedChannelListIn24g; 241 case SoftApConfiguration.BAND_5GHZ: 242 return mSupportedChannelListIn5g; 243 case SoftApConfiguration.BAND_6GHZ: 244 return mSupportedChannelListIn6g; 245 case SoftApConfiguration.BAND_60GHZ: 246 return mSupportedChannelListIn60g; 247 default: 248 throw new IllegalArgumentException("Invalid band: " + band); 249 } 250 } 251 252 /** 253 * @hide 254 */ SoftApCapability(@ullable SoftApCapability source)255 public SoftApCapability(@Nullable SoftApCapability source) { 256 if (source != null) { 257 mSupportedFeatures = source.mSupportedFeatures; 258 mMaximumSupportedClientNumber = source.mMaximumSupportedClientNumber; 259 mSupportedChannelListIn24g = source.mSupportedChannelListIn24g; 260 mSupportedChannelListIn5g = source.mSupportedChannelListIn5g; 261 mSupportedChannelListIn6g = source.mSupportedChannelListIn6g; 262 mSupportedChannelListIn60g = source.mSupportedChannelListIn60g; 263 } 264 } 265 266 /** 267 * Constructor with combination of the feature. 268 * Zero to no supported feature. 269 * 270 * @param features One or combination of {@code SOFTAP_FEATURE_}, for instance: 271 * {@link #SOFTAP_FEATURE_ACS_OFFLOAD}, {@link #SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} or 272 * {@link #SOFTAP_FEATURE_WPA3_SAE}. 273 * @hide 274 */ SoftApCapability(@otspotFeatures long features)275 public SoftApCapability(@HotspotFeatures long features) { 276 mSupportedFeatures = features; 277 } 278 279 @Override 280 /** Implement the Parcelable interface. */ describeContents()281 public int describeContents() { 282 return 0; 283 } 284 285 @Override 286 /** Implement the Parcelable interface */ writeToParcel(@onNull Parcel dest, int flags)287 public void writeToParcel(@NonNull Parcel dest, int flags) { 288 dest.writeLong(mSupportedFeatures); 289 dest.writeInt(mMaximumSupportedClientNumber); 290 dest.writeIntArray(mSupportedChannelListIn24g); 291 dest.writeIntArray(mSupportedChannelListIn5g); 292 dest.writeIntArray(mSupportedChannelListIn6g); 293 dest.writeIntArray(mSupportedChannelListIn60g); 294 } 295 296 @NonNull 297 /** Implement the Parcelable interface */ 298 public static final Creator<SoftApCapability> CREATOR = new Creator<SoftApCapability>() { 299 public SoftApCapability createFromParcel(Parcel in) { 300 SoftApCapability capability = new SoftApCapability(in.readLong()); 301 capability.mMaximumSupportedClientNumber = in.readInt(); 302 capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, in.createIntArray()); 303 capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, in.createIntArray()); 304 capability.setSupportedChannelList(SoftApConfiguration.BAND_6GHZ, in.createIntArray()); 305 capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, in.createIntArray()); 306 return capability; 307 } 308 309 public SoftApCapability[] newArray(int size) { 310 return new SoftApCapability[size]; 311 } 312 }; 313 314 @NonNull 315 @Override toString()316 public String toString() { 317 StringBuilder sbuf = new StringBuilder(); 318 sbuf.append("SupportedFeatures=").append(mSupportedFeatures); 319 sbuf.append("MaximumSupportedClientNumber=").append(mMaximumSupportedClientNumber); 320 sbuf.append("SupportedChannelListIn24g") 321 .append(Arrays.toString(mSupportedChannelListIn24g)); 322 sbuf.append("SupportedChannelListIn5g").append(Arrays.toString(mSupportedChannelListIn5g)); 323 sbuf.append("SupportedChannelListIn6g").append(Arrays.toString(mSupportedChannelListIn6g)); 324 sbuf.append("SupportedChannelListIn60g") 325 .append(Arrays.toString(mSupportedChannelListIn60g)); 326 return sbuf.toString(); 327 } 328 329 @Override equals(@onNull Object o)330 public boolean equals(@NonNull Object o) { 331 if (this == o) return true; 332 if (!(o instanceof SoftApCapability)) return false; 333 SoftApCapability capability = (SoftApCapability) o; 334 return mSupportedFeatures == capability.mSupportedFeatures 335 && mMaximumSupportedClientNumber == capability.mMaximumSupportedClientNumber 336 && Arrays.equals(mSupportedChannelListIn24g, capability.mSupportedChannelListIn24g) 337 && Arrays.equals(mSupportedChannelListIn5g, capability.mSupportedChannelListIn5g) 338 && Arrays.equals(mSupportedChannelListIn6g, capability.mSupportedChannelListIn6g) 339 && Arrays.equals(mSupportedChannelListIn60g, capability.mSupportedChannelListIn60g); 340 } 341 342 @Override hashCode()343 public int hashCode() { 344 return Objects.hash(mSupportedFeatures, mMaximumSupportedClientNumber, 345 Arrays.hashCode(mSupportedChannelListIn24g), 346 Arrays.hashCode(mSupportedChannelListIn5g), 347 Arrays.hashCode(mSupportedChannelListIn6g), 348 Arrays.hashCode(mSupportedChannelListIn60g)); 349 } 350 } 351