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 * Constructor for a MloLInk. 103 */ MloLink()104 public MloLink() { 105 mBand = WifiScanner.WIFI_BAND_UNSPECIFIED; 106 mChannel = 0; 107 mState = MLO_LINK_STATE_UNASSOCIATED; 108 mApMacAddress = null; 109 mStaMacAddress = null; 110 mLinkId = INVALID_MLO_LINK_ID; 111 } 112 113 /** 114 * Copy Constructor 115 * 116 * @hide 117 */ MloLink(MloLink source, long redactions)118 public MloLink(MloLink source, long redactions) { 119 mBand = source.mBand; 120 mChannel = source.mChannel; 121 mLinkId = source.mLinkId; 122 mState = source.mState; 123 124 mStaMacAddress = ((redactions & NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS) != 0) 125 || source.mStaMacAddress == null 126 ? null : MacAddress.fromString(source.mStaMacAddress.toString()); 127 128 mApMacAddress = ((redactions & NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION) != 0) 129 || source.mApMacAddress == null 130 ? null : MacAddress.fromString(source.mApMacAddress.toString()); 131 } 132 133 /** Returns the Wi-Fi band of this link as one of: 134 * {@link WifiScanner#WIFI_BAND_UNSPECIFIED}, 135 * {@link WifiScanner#WIFI_BAND_24_GHZ}, 136 * {@link WifiScanner#WIFI_BAND_5_GHZ}, 137 * {@link WifiScanner#WIFI_BAND_6_GHZ} 138 */ getBand()139 public @WifiAnnotations.WifiBandBasic int getBand() { 140 return mBand; 141 } 142 143 /** 144 * Returns the channel number of this link. 145 * A valid value is based on the 802.11 specification in sections 19.3.15 and 27.3.23 146 */ 147 @IntRange(from = 1) getChannel()148 public int getChannel() { 149 return mChannel; 150 } 151 152 /** 153 * Returns the link id of this link. 154 * Valid values are 0-15, as described in IEEE 802.11be Specification, section 9.4.2.295b.2. 155 * 156 * @return {@link #INVALID_MLO_LINK_ID} or a valid value (0-15). 157 */ 158 @IntRange(from = INVALID_MLO_LINK_ID, to = MAX_MLO_LINK_ID) getLinkId()159 public int getLinkId() { 160 return mLinkId; 161 } 162 163 /** Returns the state of this link as one of: 164 * {@link #MLO_LINK_STATE_INVALID} 165 * {@link #MLO_LINK_STATE_UNASSOCIATED} 166 * {@link #MLO_LINK_STATE_IDLE} 167 * {@link #MLO_LINK_STATE_ACTIVE} 168 */ getState()169 public @MloLinkState int getState() { 170 return mState; 171 } 172 173 /** 174 * Returns the AP MAC address of this link. 175 * 176 * @return AP MAC address for this link or null when the caller has insufficient 177 * permissions to access the access point MAC Address. 178 */ getApMacAddress()179 public @Nullable MacAddress getApMacAddress() { 180 return mApMacAddress; 181 } 182 183 /** 184 * Returns the STA MAC address of this link. 185 * 186 * @return STA MAC address assigned for this link, or null in the following cases: 187 * <ul> 188 * <li> The caller has insufficient permissions to access the STA MAC Address </li> 189 * <li> Link is not associated, hence no MAC address is assigned to it by STA </li> 190 * </ul> 191 */ getStaMacAddress()192 public @Nullable MacAddress getStaMacAddress() { 193 return mStaMacAddress; 194 } 195 196 /** 197 * Sets the channel number of this link. 198 * 199 * @hide 200 */ setChannel(int channel)201 public void setChannel(int channel) { 202 mChannel = channel; 203 } 204 205 /** 206 * Sets the band for this link 207 * 208 * @hide 209 */ setBand(@ifiAnnotations.WifiBandBasic int band)210 public void setBand(@WifiAnnotations.WifiBandBasic int band) { 211 mBand = band; 212 } 213 214 /** 215 * Sets the linkId of this link 216 * 217 * @hide 218 */ setLinkId(int linkId)219 public void setLinkId(int linkId) { 220 mLinkId = linkId; 221 } 222 223 /** 224 * Sets the state of this link 225 * 226 * @hide 227 */ setState(@loLinkState int state)228 public void setState(@MloLinkState int state) { 229 mState = state; 230 } 231 232 /** 233 * set the AP MAC Address for this link 234 * 235 * @hide 236 */ setApMacAddress(MacAddress address)237 public void setApMacAddress(MacAddress address) { 238 mApMacAddress = address; 239 } 240 241 /** 242 * set the STA MAC Address for this link 243 * 244 * @hide 245 */ setStaMacAddress(MacAddress address)246 public void setStaMacAddress(MacAddress address) { 247 mStaMacAddress = address; 248 } 249 250 @Override equals(@ullable Object o)251 public boolean equals(@Nullable Object o) { 252 if (this == o) return true; 253 if (o == null || getClass() != o.getClass()) return false; 254 MloLink that = (MloLink) o; 255 return mBand == that.mBand 256 && mChannel == that.mChannel 257 && mLinkId == that.mLinkId 258 && Objects.equals(mApMacAddress, that.mApMacAddress) 259 && Objects.equals(mStaMacAddress, that.mStaMacAddress) 260 && mState == that.mState; 261 } 262 263 @Override hashCode()264 public int hashCode() { 265 return Objects.hash(mBand, mChannel, mLinkId, mApMacAddress, mStaMacAddress, mState); 266 } 267 getStateString(@loLinkState int state)268 private String getStateString(@MloLinkState int state) { 269 switch(state) { 270 case MLO_LINK_STATE_INVALID: 271 return "MLO_LINK_STATE_INVALID"; 272 case MLO_LINK_STATE_UNASSOCIATED: 273 return "MLO_LINK_STATE_UNASSOCIATED"; 274 case MLO_LINK_STATE_IDLE: 275 return "MLO_LINK_STATE_IDLE"; 276 case MLO_LINK_STATE_ACTIVE: 277 return "MLO_LINK_STATE_ACTIVE"; 278 default: 279 return "Unknown MLO link state"; 280 } 281 } 282 283 /** 284 * @hide 285 */ isValidState(@loLinkState int state)286 public static boolean isValidState(@MloLinkState int state) { 287 switch(state) { 288 case MLO_LINK_STATE_INVALID: 289 case MLO_LINK_STATE_UNASSOCIATED: 290 case MLO_LINK_STATE_IDLE: 291 case MLO_LINK_STATE_ACTIVE: 292 return true; 293 } 294 return false; 295 } 296 297 @Override toString()298 public String toString() { 299 StringBuilder sb = new StringBuilder("MloLink{"); 300 if (mBand == WIFI_BAND_24_GHZ) { 301 sb.append("2.4GHz"); 302 } else if (mBand == WIFI_BAND_5_GHZ) { 303 sb.append("5GHz"); 304 } else if (mBand == WIFI_BAND_6_GHZ) { 305 sb.append("6GHz"); 306 } else { 307 sb.append("UNKNOWN BAND"); 308 } 309 sb.append(", channel: ").append(mChannel); 310 sb.append(", id: ").append(mLinkId); 311 sb.append(", state: ").append(getStateString(mState)); 312 if (mApMacAddress != null) { 313 sb.append(", AP MAC Address: ").append(mApMacAddress.toString()); 314 } 315 if (mStaMacAddress != null) { 316 sb.append(", STA MAC Address: ").append(mStaMacAddress.toString()); 317 } 318 sb.append('}'); 319 return sb.toString(); 320 } 321 322 /** Implement the Parcelable interface */ 323 @Override describeContents()324 public int describeContents() { 325 return 0; 326 } 327 328 /** Implement the Parcelable interface */ 329 @Override writeToParcel(@onNull Parcel dest, int flags)330 public void writeToParcel(@NonNull Parcel dest, int flags) { 331 dest.writeInt(mBand); 332 dest.writeInt(mChannel); 333 dest.writeInt(mLinkId); 334 dest.writeInt(mState); 335 dest.writeParcelable(mApMacAddress, flags); 336 dest.writeParcelable(mStaMacAddress, flags); 337 } 338 339 /** Implement the Parcelable interface */ 340 public static final @NonNull Creator<MloLink> CREATOR = 341 new Creator<MloLink>() { 342 public MloLink createFromParcel(Parcel in) { 343 MloLink link = new MloLink(); 344 link.mBand = in.readInt(); 345 link.mChannel = in.readInt(); 346 link.mLinkId = in.readInt(); 347 link.mState = in.readInt(); 348 link.mApMacAddress = in.readParcelable(MacAddress.class.getClassLoader()); 349 link.mStaMacAddress = in.readParcelable(MacAddress.class.getClassLoader()); 350 return link; 351 } 352 353 public MloLink[] newArray(int size) { 354 return new MloLink[size]; 355 } 356 }; 357 } 358