1 /* 2 * Copyright (C) 2022 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 static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ; 20 import static android.net.wifi.WifiScanner.WIFI_BAND_5_GHZ; 21 import static android.net.wifi.WifiScanner.WIFI_BAND_6_GHZ; 22 23 import android.annotation.IntDef; 24 import android.annotation.IntRange; 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.net.MacAddress; 28 import android.net.NetworkCapabilities; 29 import android.os.Parcel; 30 import android.os.Parcelable; 31 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 import java.util.Objects; 35 36 /** 37 * Data structure class representing a Wi-Fi Multi-Link Operation (MLO) link 38 * This is only used by 802.11be capable devices 39 */ 40 public final class MloLink implements Parcelable { 41 42 /** 43 * Invalid link id. Used in {link #getLinkId()} 44 */ 45 public static final int INVALID_MLO_LINK_ID = -1; 46 47 /** 48 * Lower limit for MLO link id 49 * As described in IEEE 802.11be Specification, section 9.4.2.295b.2. 50 * 51 * @hide 52 */ 53 public static final int MIN_MLO_LINK_ID = 0; 54 55 /** 56 * Upper limit for MLO link id 57 * As described in IEEE 802.11be Specification, section 9.4.2.295b.2. 58 * 59 * @hide 60 */ 61 public static final int MAX_MLO_LINK_ID = 15; 62 63 /** 64 * MLO link state: Invalid link state. Used in {link #getState()} 65 */ 66 public static final int MLO_LINK_STATE_INVALID = 0; 67 /** 68 * MLO link state: Link is not associated with the access point. Used in {link #getState()} 69 */ 70 public static final int MLO_LINK_STATE_UNASSOCIATED = 1; 71 /** 72 * MLO link state: Link is associated to the access point but not mapped to any traffic stream. 73 * Used in {link #getState()} 74 */ 75 public static final int MLO_LINK_STATE_IDLE = 2; 76 /** 77 * MLO link state: Link is associated to the access point and mapped to at least one traffic 78 * stream. {link #getState()} 79 * Note that an MLO link could be in that state but in power save mode. 80 */ 81 public static final int MLO_LINK_STATE_ACTIVE = 3; 82 83 /** 84 * @hide 85 */ 86 @Retention(RetentionPolicy.SOURCE) 87 @IntDef(prefix = {"MLO_LINK_STATE_"}, value = { 88 MLO_LINK_STATE_INVALID, 89 MLO_LINK_STATE_UNASSOCIATED, 90 MLO_LINK_STATE_IDLE, 91 MLO_LINK_STATE_ACTIVE}) 92 public @interface MloLinkState {}; 93 94 private int mLinkId; 95 private MacAddress mApMacAddress; 96 private MacAddress mStaMacAddress; 97 private @MloLinkState int mState; 98 private @WifiAnnotations.WifiBandBasic int mBand; 99 private int mChannel; 100 101 /** 102 * Received Signal Strength Indicator 103 */ 104 private int mRssi; 105 106 /** 107 * Rx(receive) Link speed in Mbps 108 */ 109 private int mRxLinkSpeed; 110 111 /** 112 * Tx(transmit) Link speed in Mbps 113 */ 114 private int mTxLinkSpeed; 115 116 /** 117 * Constructor for a MloLInk. 118 */ MloLink()119 public MloLink() { 120 mBand = WifiScanner.WIFI_BAND_UNSPECIFIED; 121 mChannel = 0; 122 mState = MLO_LINK_STATE_UNASSOCIATED; 123 mApMacAddress = null; 124 mStaMacAddress = null; 125 mLinkId = INVALID_MLO_LINK_ID; 126 mRssi = WifiInfo.INVALID_RSSI; 127 mRxLinkSpeed = WifiInfo.LINK_SPEED_UNKNOWN; 128 mTxLinkSpeed = WifiInfo.LINK_SPEED_UNKNOWN; 129 } 130 131 /** 132 * Copy Constructor 133 * 134 * @hide 135 */ MloLink(MloLink source, long redactions)136 public MloLink(MloLink source, long redactions) { 137 mBand = source.mBand; 138 mChannel = source.mChannel; 139 mLinkId = source.mLinkId; 140 mState = source.mState; 141 mRssi = source.mRssi; 142 mRxLinkSpeed = source.mRxLinkSpeed; 143 mTxLinkSpeed = source.mTxLinkSpeed; 144 145 mStaMacAddress = ((redactions & NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS) != 0) 146 || source.mStaMacAddress == null 147 ? null : MacAddress.fromString(source.mStaMacAddress.toString()); 148 149 mApMacAddress = ((redactions & NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION) != 0) 150 || source.mApMacAddress == null 151 ? null : MacAddress.fromString(source.mApMacAddress.toString()); 152 } 153 154 /** Returns the Wi-Fi band of this link as one of: 155 * {@link WifiScanner#WIFI_BAND_UNSPECIFIED}, 156 * {@link WifiScanner#WIFI_BAND_24_GHZ}, 157 * {@link WifiScanner#WIFI_BAND_5_GHZ}, 158 * {@link WifiScanner#WIFI_BAND_6_GHZ} 159 */ getBand()160 public @WifiAnnotations.WifiBandBasic int getBand() { 161 return mBand; 162 } 163 164 /** 165 * Returns the channel number of this link. 166 * A valid value is based on the 802.11 specification in sections 19.3.15 and 27.3.23 167 */ 168 @IntRange(from = 1) getChannel()169 public int getChannel() { 170 return mChannel; 171 } 172 173 /** 174 * Returns the link id of this link. 175 * Valid values are 0-15, as described in IEEE 802.11be Specification, section 9.4.2.295b.2. 176 * 177 * @return {@link #INVALID_MLO_LINK_ID} or a valid value (0-15). 178 */ 179 @IntRange(from = INVALID_MLO_LINK_ID, to = MAX_MLO_LINK_ID) getLinkId()180 public int getLinkId() { 181 return mLinkId; 182 } 183 184 /** Returns the state of this link as one of: 185 * {@link #MLO_LINK_STATE_INVALID} 186 * {@link #MLO_LINK_STATE_UNASSOCIATED} 187 * {@link #MLO_LINK_STATE_IDLE} 188 * {@link #MLO_LINK_STATE_ACTIVE} 189 */ getState()190 public @MloLinkState int getState() { 191 return mState; 192 } 193 194 /** 195 * Returns the AP MAC address of this link. 196 * 197 * @return AP MAC address for this link or null when the caller has insufficient 198 * permissions to access the access point MAC Address. 199 */ getApMacAddress()200 public @Nullable MacAddress getApMacAddress() { 201 return mApMacAddress; 202 } 203 204 /** 205 * Returns the STA MAC address of this link. 206 * 207 * @return STA MAC address assigned for this link, or null in the following cases: 208 * <ul> 209 * <li> The caller has insufficient permissions to access the STA MAC Address </li> 210 * <li> Link is not associated, hence no MAC address is assigned to it by STA </li> 211 * </ul> 212 */ getStaMacAddress()213 public @Nullable MacAddress getStaMacAddress() { 214 return mStaMacAddress; 215 } 216 217 /** 218 * Sets the channel number of this link. 219 * 220 * @hide 221 */ setChannel(int channel)222 public void setChannel(int channel) { 223 mChannel = channel; 224 } 225 226 /** 227 * Sets the band for this link 228 * 229 * @hide 230 */ setBand(@ifiAnnotations.WifiBandBasic int band)231 public void setBand(@WifiAnnotations.WifiBandBasic int band) { 232 mBand = band; 233 } 234 235 /** 236 * Sets the linkId of this link 237 * 238 * @hide 239 */ setLinkId(int linkId)240 public void setLinkId(int linkId) { 241 mLinkId = linkId; 242 } 243 244 /** 245 * Sets the state of this link 246 * 247 * @hide 248 */ setState(@loLinkState int state)249 public void setState(@MloLinkState int state) { 250 mState = state; 251 } 252 253 /** 254 * set the AP MAC Address for this link 255 * 256 * @hide 257 */ setApMacAddress(MacAddress address)258 public void setApMacAddress(MacAddress address) { 259 mApMacAddress = address; 260 } 261 262 /** 263 * set the STA MAC Address for this link 264 * 265 * @hide 266 */ setStaMacAddress(MacAddress address)267 public void setStaMacAddress(MacAddress address) { 268 mStaMacAddress = address; 269 } 270 271 /** 272 * Update the last received packet bit rate in Mbps. 273 * @hide 274 */ setRxLinkSpeedMbps(int rxLinkSpeed)275 public void setRxLinkSpeedMbps(int rxLinkSpeed) { 276 mRxLinkSpeed = rxLinkSpeed; 277 } 278 279 /** 280 * Returns the current receive link speed in Mbps. 281 * @return the Rx link speed or {@link WifiInfo#LINK_SPEED_UNKNOWN} if link speed is unknown. 282 * @see WifiInfo#LINK_SPEED_UNKNOWN 283 */ 284 @IntRange(from = -1) getRxLinkSpeedMbps()285 public int getRxLinkSpeedMbps() { 286 return mRxLinkSpeed; 287 } 288 289 /** 290 * Update the last transmitted packet bit rate in Mbps. 291 * @hide 292 */ setTxLinkSpeedMbps(int txLinkSpeed)293 public void setTxLinkSpeedMbps(int txLinkSpeed) { 294 mTxLinkSpeed = txLinkSpeed; 295 } 296 297 /** 298 * Returns the current transmit link speed in Mbps. 299 * @return the Tx link speed or {@link WifiInfo#LINK_SPEED_UNKNOWN} if link speed is unknown. 300 * @see WifiInfo#LINK_SPEED_UNKNOWN 301 */ 302 @IntRange(from = -1) getTxLinkSpeedMbps()303 public int getTxLinkSpeedMbps() { 304 return mTxLinkSpeed; 305 } 306 307 /** 308 * Sets the RSSI of the link. 309 * 310 * @param rssi RSSI in dBM. 311 * @hide 312 */ setRssi(int rssi)313 public void setRssi(int rssi) { 314 if (rssi < WifiInfo.INVALID_RSSI) rssi = WifiInfo.INVALID_RSSI; 315 if (rssi > WifiInfo.MAX_RSSI) rssi = WifiInfo.MAX_RSSI; 316 mRssi = rssi; 317 } 318 319 /** 320 * Returns the RSSI of the link. 321 * 322 * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into 323 * an absolute signal level which can be displayed to a user. 324 * 325 * @return RSSI in dBM. 326 */ getRssi()327 public int getRssi() { 328 return mRssi; 329 } 330 331 @Override equals(@ullable Object o)332 public boolean equals(@Nullable Object o) { 333 if (this == o) return true; 334 if (o == null || getClass() != o.getClass()) return false; 335 MloLink that = (MloLink) o; 336 return mBand == that.mBand 337 && mChannel == that.mChannel 338 && mLinkId == that.mLinkId 339 && Objects.equals(mApMacAddress, that.mApMacAddress) 340 && Objects.equals(mStaMacAddress, that.mStaMacAddress) 341 && mState == that.mState 342 && mRssi == that.mRssi 343 && mRxLinkSpeed == that.mRxLinkSpeed 344 && mTxLinkSpeed == that.mTxLinkSpeed; 345 } 346 347 @Override hashCode()348 public int hashCode() { 349 return Objects.hash(mBand, mChannel, mLinkId, mApMacAddress, mStaMacAddress, mState); 350 } 351 getStateString(@loLinkState int state)352 private String getStateString(@MloLinkState int state) { 353 switch(state) { 354 case MLO_LINK_STATE_INVALID: 355 return "MLO_LINK_STATE_INVALID"; 356 case MLO_LINK_STATE_UNASSOCIATED: 357 return "MLO_LINK_STATE_UNASSOCIATED"; 358 case MLO_LINK_STATE_IDLE: 359 return "MLO_LINK_STATE_IDLE"; 360 case MLO_LINK_STATE_ACTIVE: 361 return "MLO_LINK_STATE_ACTIVE"; 362 default: 363 return "Unknown MLO link state"; 364 } 365 } 366 367 /** 368 * @hide 369 */ isValidState(@loLinkState int state)370 public static boolean isValidState(@MloLinkState int state) { 371 switch(state) { 372 case MLO_LINK_STATE_INVALID: 373 case MLO_LINK_STATE_UNASSOCIATED: 374 case MLO_LINK_STATE_IDLE: 375 case MLO_LINK_STATE_ACTIVE: 376 return true; 377 } 378 return false; 379 } 380 381 @Override toString()382 public String toString() { 383 StringBuilder sb = new StringBuilder("MloLink{"); 384 if (mBand == WIFI_BAND_24_GHZ) { 385 sb.append("2.4GHz"); 386 } else if (mBand == WIFI_BAND_5_GHZ) { 387 sb.append("5GHz"); 388 } else if (mBand == WIFI_BAND_6_GHZ) { 389 sb.append("6GHz"); 390 } else { 391 sb.append("UNKNOWN BAND"); 392 } 393 sb.append(", channel: ").append(mChannel); 394 sb.append(", id: ").append(mLinkId); 395 sb.append(", state: ").append(getStateString(mState)); 396 sb.append(", RSSI: ").append(getRssi()); 397 sb.append(", Rx Link speed: ").append(getRxLinkSpeedMbps()).append( 398 WifiInfo.LINK_SPEED_UNITS); 399 sb.append(", Tx Link speed: ").append(getTxLinkSpeedMbps()).append( 400 WifiInfo.LINK_SPEED_UNITS); 401 if (mApMacAddress != null) { 402 sb.append(", AP MAC Address: ").append(mApMacAddress.toString()); 403 } 404 if (mStaMacAddress != null) { 405 sb.append(", STA MAC Address: ").append(mStaMacAddress.toString()); 406 } 407 sb.append('}'); 408 return sb.toString(); 409 } 410 411 /** Implement the Parcelable interface */ 412 @Override describeContents()413 public int describeContents() { 414 return 0; 415 } 416 417 /** Implement the Parcelable interface */ 418 @Override writeToParcel(@onNull Parcel dest, int flags)419 public void writeToParcel(@NonNull Parcel dest, int flags) { 420 dest.writeInt(mBand); 421 dest.writeInt(mChannel); 422 dest.writeInt(mLinkId); 423 dest.writeInt(mState); 424 dest.writeInt(mRssi); 425 dest.writeInt(mRxLinkSpeed); 426 dest.writeInt(mTxLinkSpeed); 427 dest.writeParcelable(mApMacAddress, flags); 428 dest.writeParcelable(mStaMacAddress, flags); 429 } 430 431 /** Implement the Parcelable interface */ 432 public static final @NonNull Creator<MloLink> CREATOR = 433 new Creator<MloLink>() { 434 public MloLink createFromParcel(Parcel in) { 435 MloLink link = new MloLink(); 436 link.mBand = in.readInt(); 437 link.mChannel = in.readInt(); 438 link.mLinkId = in.readInt(); 439 link.mState = in.readInt(); 440 link.mRssi = in.readInt(); 441 link.mRxLinkSpeed = in.readInt(); 442 link.mTxLinkSpeed = in.readInt(); 443 link.mApMacAddress = in.readParcelable(MacAddress.class.getClassLoader()); 444 link.mStaMacAddress = in.readParcelable(MacAddress.class.getClassLoader()); 445 return link; 446 } 447 448 public MloLink[] newArray(int size) { 449 return new MloLink[size]; 450 } 451 }; 452 } 453