1 /* 2 * Copyright (C) 2020 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.nl80211; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.NonNull; 21 import android.annotation.SystemApi; 22 import android.net.wifi.ScanResult; 23 import android.net.wifi.WifiAnnotations.ChannelWidth; 24 import android.net.wifi.WifiAnnotations.WifiStandard; 25 import android.net.wifi.flags.Flags; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.util.Log; 29 30 import java.util.Objects; 31 32 /** 33 * DeviceWiphyCapabilities for wificond 34 * 35 * Contains the WiFi physical layer attributes and capabilities of the device. 36 * It is used to collect these attributes from the device driver via wificond. 37 * 38 * @hide 39 */ 40 @SystemApi 41 public final class DeviceWiphyCapabilities implements Parcelable { 42 private static final String TAG = "DeviceWiphyCapabilities"; 43 44 private boolean m80211nSupported; 45 private boolean m80211acSupported; 46 private boolean m80211axSupported; 47 private boolean m80211beSupported; 48 private boolean mChannelWidth160MhzSupported; 49 private boolean mChannelWidth80p80MhzSupported; 50 private boolean mChannelWidth320MhzSupported; 51 private int mMaxNumberTxSpatialStreams; 52 private int mMaxNumberRxSpatialStreams; 53 private int mMaxNumberAkms; 54 55 56 /** public constructor */ DeviceWiphyCapabilities()57 public DeviceWiphyCapabilities() { 58 m80211nSupported = false; 59 m80211acSupported = false; 60 m80211axSupported = false; 61 m80211beSupported = false; 62 mChannelWidth160MhzSupported = false; 63 mChannelWidth80p80MhzSupported = false; 64 mChannelWidth320MhzSupported = false; 65 mMaxNumberTxSpatialStreams = 1; 66 mMaxNumberRxSpatialStreams = 1; 67 mMaxNumberAkms = 1; 68 } 69 70 /** 71 * Get the IEEE 802.11 standard support 72 * 73 * @param standard the IEEE 802.11 standard to check on its support. 74 * valid values from {@link ScanResult}'s {@code WIFI_STANDARD_} 75 * @return {@code true} if supported, {@code false} otherwise. 76 */ isWifiStandardSupported(@ifiStandard int standard)77 public boolean isWifiStandardSupported(@WifiStandard int standard) { 78 switch (standard) { 79 case ScanResult.WIFI_STANDARD_LEGACY: 80 return true; 81 case ScanResult.WIFI_STANDARD_11N: 82 return m80211nSupported; 83 case ScanResult.WIFI_STANDARD_11AC: 84 return m80211acSupported; 85 case ScanResult.WIFI_STANDARD_11AX: 86 return m80211axSupported; 87 case ScanResult.WIFI_STANDARD_11BE: 88 return m80211beSupported; 89 default: 90 Log.e(TAG, "isWifiStandardSupported called with invalid standard: " + standard); 91 return false; 92 } 93 } 94 95 /** 96 * Set the IEEE 802.11 standard support 97 * 98 * @param standard the IEEE 802.11 standard to set its support. 99 * valid values from {@link ScanResult}'s {@code WIFI_STANDARD_} 100 * @param support {@code true} if supported, {@code false} otherwise. 101 */ setWifiStandardSupport(@ifiStandard int standard, boolean support)102 public void setWifiStandardSupport(@WifiStandard int standard, boolean support) { 103 switch (standard) { 104 case ScanResult.WIFI_STANDARD_11N: 105 m80211nSupported = support; 106 break; 107 case ScanResult.WIFI_STANDARD_11AC: 108 m80211acSupported = support; 109 break; 110 case ScanResult.WIFI_STANDARD_11AX: 111 m80211axSupported = support; 112 break; 113 case ScanResult.WIFI_STANDARD_11BE: 114 m80211beSupported = support; 115 break; 116 default: 117 Log.e(TAG, "setWifiStandardSupport called with invalid standard: " + standard); 118 } 119 } 120 121 /** 122 * Get the support for channel bandwidth 123 * 124 * @param chWidth valid values from {@link ScanResult}'s {@code CHANNEL_WIDTH_} 125 * 126 * @return {@code true} if supported, {@code false} otherwise. 127 */ isChannelWidthSupported(@hannelWidth int chWidth)128 public boolean isChannelWidthSupported(@ChannelWidth int chWidth) { 129 switch (chWidth) { 130 case ScanResult.CHANNEL_WIDTH_20MHZ: 131 return true; 132 case ScanResult.CHANNEL_WIDTH_40MHZ: 133 return (m80211nSupported || m80211acSupported || m80211axSupported 134 || m80211beSupported); 135 case ScanResult.CHANNEL_WIDTH_80MHZ: 136 return (m80211acSupported || m80211axSupported || m80211beSupported); 137 case ScanResult.CHANNEL_WIDTH_160MHZ: 138 return mChannelWidth160MhzSupported; 139 case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: 140 return mChannelWidth80p80MhzSupported; 141 case ScanResult.CHANNEL_WIDTH_320MHZ: 142 return mChannelWidth320MhzSupported; 143 default: 144 Log.e(TAG, "isChannelWidthSupported called with invalid channel width: " + chWidth); 145 } 146 return false; 147 } 148 149 /** 150 * Set support for channel bandwidth 151 * 152 * @param chWidth valid values are {@link ScanResult#CHANNEL_WIDTH_160MHZ}, 153 * {@link ScanResult#CHANNEL_WIDTH_80MHZ_PLUS_MHZ} and 154 * {@link ScanResult#CHANNEL_WIDTH_320MHZ} 155 * @param support {@code true} if supported, {@code false} otherwise. 156 * 157 * @hide 158 */ setChannelWidthSupported(@hannelWidth int chWidth, boolean support)159 public void setChannelWidthSupported(@ChannelWidth int chWidth, boolean support) { 160 switch (chWidth) { 161 case ScanResult.CHANNEL_WIDTH_160MHZ: 162 mChannelWidth160MhzSupported = support; 163 break; 164 case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: 165 mChannelWidth80p80MhzSupported = support; 166 break; 167 case ScanResult.CHANNEL_WIDTH_320MHZ: 168 mChannelWidth320MhzSupported = support; 169 break; 170 default: 171 Log.e(TAG, "setChannelWidthSupported called with Invalid channel width: " 172 + chWidth); 173 } 174 } 175 176 /** 177 * Get maximum number of transmit spatial streams 178 * 179 * @return number of spatial streams 180 */ getMaxNumberTxSpatialStreams()181 public int getMaxNumberTxSpatialStreams() { 182 return mMaxNumberTxSpatialStreams; 183 } 184 185 /** 186 * Set maximum number of transmit spatial streams 187 * 188 * @param streams number of spatial streams 189 * 190 * @hide 191 */ setMaxNumberTxSpatialStreams(int streams)192 public void setMaxNumberTxSpatialStreams(int streams) { 193 mMaxNumberTxSpatialStreams = streams; 194 } 195 196 /** 197 * Get maximum number of receive spatial streams 198 * 199 * @return number of streams 200 */ getMaxNumberRxSpatialStreams()201 public int getMaxNumberRxSpatialStreams() { 202 return mMaxNumberRxSpatialStreams; 203 } 204 205 /** 206 * Get the maximum number of AKM suites supported in the connection request to the driver. 207 * 208 * @return maximum number of AKMs 209 */ 210 @FlaggedApi(Flags.FLAG_GET_DEVICE_CROSS_AKM_ROAMING_SUPPORT) getMaxNumberAkms()211 public int getMaxNumberAkms() { 212 return mMaxNumberAkms; 213 } 214 215 /** 216 * Set the maximum number of AKM suites supported in the connection request to the driver. 217 * 218 * @hide 219 */ setMaxNumberAkms(int akms)220 public void setMaxNumberAkms(int akms) { 221 mMaxNumberAkms = akms; 222 } 223 224 /** 225 * Set maximum number of receive spatial streams 226 * 227 * @param streams number of streams 228 * 229 * @hide 230 */ setMaxNumberRxSpatialStreams(int streams)231 public void setMaxNumberRxSpatialStreams(int streams) { 232 mMaxNumberRxSpatialStreams = streams; 233 } 234 235 /** override comparator */ 236 @Override equals(Object rhs)237 public boolean equals(Object rhs) { 238 if (this == rhs) return true; 239 if (!(rhs instanceof DeviceWiphyCapabilities)) { 240 return false; 241 } 242 DeviceWiphyCapabilities capa = (DeviceWiphyCapabilities) rhs; 243 244 return m80211nSupported == capa.m80211nSupported 245 && m80211acSupported == capa.m80211acSupported 246 && m80211axSupported == capa.m80211axSupported 247 && m80211beSupported == capa.m80211beSupported 248 && mChannelWidth160MhzSupported == capa.mChannelWidth160MhzSupported 249 && mChannelWidth80p80MhzSupported == capa.mChannelWidth80p80MhzSupported 250 && mChannelWidth320MhzSupported == capa.mChannelWidth320MhzSupported 251 && mMaxNumberTxSpatialStreams == capa.mMaxNumberTxSpatialStreams 252 && mMaxNumberRxSpatialStreams == capa.mMaxNumberRxSpatialStreams 253 && mMaxNumberAkms == capa.mMaxNumberAkms; 254 } 255 256 /** override hash code */ 257 @Override hashCode()258 public int hashCode() { 259 return Objects.hash(m80211nSupported, m80211acSupported, m80211axSupported, 260 m80211beSupported, mChannelWidth160MhzSupported, mChannelWidth80p80MhzSupported, 261 mChannelWidth320MhzSupported, mMaxNumberTxSpatialStreams, 262 mMaxNumberRxSpatialStreams, mMaxNumberAkms); 263 } 264 265 /** implement Parcelable interface */ 266 @Override describeContents()267 public int describeContents() { 268 return 0; 269 } 270 271 /** 272 * implement Parcelable interface 273 * |flags| is ignored. 274 */ 275 @Override writeToParcel(@onNull Parcel out, int flags)276 public void writeToParcel(@NonNull Parcel out, int flags) { 277 out.writeBoolean(m80211nSupported); 278 out.writeBoolean(m80211acSupported); 279 out.writeBoolean(m80211axSupported); 280 out.writeBoolean(m80211beSupported); 281 out.writeBoolean(mChannelWidth160MhzSupported); 282 out.writeBoolean(mChannelWidth80p80MhzSupported); 283 out.writeBoolean(mChannelWidth320MhzSupported); 284 out.writeInt(mMaxNumberTxSpatialStreams); 285 out.writeInt(mMaxNumberRxSpatialStreams); 286 out.writeInt(mMaxNumberAkms); 287 } 288 289 @Override toString()290 public String toString() { 291 StringBuilder sb = new StringBuilder(); 292 sb.append("m80211nSupported:").append(m80211nSupported ? "Yes" : "No"); 293 sb.append("m80211acSupported:").append(m80211acSupported ? "Yes" : "No"); 294 sb.append("m80211axSupported:").append(m80211axSupported ? "Yes" : "No"); 295 sb.append("m80211beSupported:").append(m80211beSupported ? "Yes" : "No"); 296 sb.append("mChannelWidth160MhzSupported: ") 297 .append(mChannelWidth160MhzSupported ? "Yes" : "No"); 298 sb.append("mChannelWidth80p80MhzSupported: ") 299 .append(mChannelWidth80p80MhzSupported ? "Yes" : "No"); 300 sb.append("mChannelWidth320MhzSupported: ") 301 .append(mChannelWidth320MhzSupported ? "Yes" : "No"); 302 sb.append("mMaxNumberTxSpatialStreams: ").append(mMaxNumberTxSpatialStreams); 303 sb.append("mMaxNumberRxSpatialStreams: ").append(mMaxNumberRxSpatialStreams); 304 sb.append("mMaxNumberAkms: ").append(mMaxNumberAkms); 305 306 return sb.toString(); 307 } 308 309 /** implement Parcelable interface */ 310 public static final @NonNull Parcelable.Creator<DeviceWiphyCapabilities> CREATOR = 311 new Parcelable.Creator<DeviceWiphyCapabilities>() { 312 /** 313 * Caller is responsible for providing a valid parcel. 314 */ 315 @Override 316 public DeviceWiphyCapabilities createFromParcel(Parcel in) { 317 DeviceWiphyCapabilities capabilities = new DeviceWiphyCapabilities(); 318 capabilities.m80211nSupported = in.readBoolean(); 319 capabilities.m80211acSupported = in.readBoolean(); 320 capabilities.m80211axSupported = in.readBoolean(); 321 capabilities.m80211beSupported = in.readBoolean(); 322 capabilities.mChannelWidth160MhzSupported = in.readBoolean(); 323 capabilities.mChannelWidth80p80MhzSupported = in.readBoolean(); 324 capabilities.mChannelWidth320MhzSupported = in.readBoolean(); 325 capabilities.mMaxNumberTxSpatialStreams = in.readInt(); 326 capabilities.mMaxNumberRxSpatialStreams = in.readInt(); 327 capabilities.mMaxNumberAkms = in.readInt(); 328 return capabilities; 329 } 330 331 @Override 332 public DeviceWiphyCapabilities[] newArray(int size) { 333 return new DeviceWiphyCapabilities[size]; 334 } 335 }; 336 } 337