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