1 /* 2 * Copyright (C) 2008 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.FlaggedApi; 20 import android.annotation.IntDef; 21 import android.annotation.IntRange; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.SystemApi; 25 import android.compat.annotation.UnsupportedAppUsage; 26 import android.net.MacAddress; 27 import android.net.wifi.WifiAnnotations.ChannelWidth; 28 import android.net.wifi.WifiAnnotations.WifiStandard; 29 import android.net.wifi.util.ScanResultUtil; 30 import android.os.Build; 31 import android.os.Parcel; 32 import android.os.Parcelable; 33 import android.util.Log; 34 35 import com.android.modules.utils.build.SdkLevel; 36 import com.android.wifi.flags.Flags; 37 38 import java.lang.annotation.Retention; 39 import java.lang.annotation.RetentionPolicy; 40 import java.nio.ByteBuffer; 41 import java.util.ArrayList; 42 import java.util.Arrays; 43 import java.util.Collections; 44 import java.util.List; 45 import java.util.Objects; 46 47 /** 48 * Describes information about a detected access point. In addition 49 * to the attributes described here, the supplicant keeps track of 50 * {@code quality}, {@code noise}, and {@code maxbitrate} attributes, 51 * but does not currently report them to external clients. 52 */ 53 public final class ScanResult implements Parcelable { 54 55 private static final String TAG = "ScanResult"; 56 /** 57 * The network name. 58 * 59 * @deprecated Use {@link #getWifiSsid()} instead. 60 */ 61 @Deprecated 62 public String SSID; 63 64 /** 65 * Ascii encoded SSID. This will replace SSID when we deprecate it. @hide 66 * 67 * @deprecated Use {@link #getWifiSsid()} instead. 68 */ 69 @Deprecated 70 // TODO(b/231433398): add maxTargetSdk = Build.VERSION_CODES.S 71 @UnsupportedAppUsage(publicAlternatives = "{@link #getWifiSsid()}") 72 public WifiSsid wifiSsid; 73 74 /** 75 * Set the SSID of the access point. 76 * @hide 77 */ 78 @SystemApi setWifiSsid(@onNull WifiSsid ssid)79 public void setWifiSsid(@NonNull WifiSsid ssid) { 80 wifiSsid = ssid; 81 CharSequence utf8Text = wifiSsid.getUtf8Text(); 82 SSID = utf8Text != null ? utf8Text.toString() : WifiManager.UNKNOWN_SSID; 83 } 84 85 /** 86 * The SSID of the access point. 87 */ 88 @Nullable getWifiSsid()89 public WifiSsid getWifiSsid() { 90 return wifiSsid; 91 } 92 93 /** 94 * The address of the access point. 95 */ 96 public String BSSID; 97 98 /** 99 * The Multi-Link Device (MLD) address of the access point. 100 * Only applicable for Wi-Fi 7 access points, null otherwise. 101 */ 102 private MacAddress mApMldMacAddress; 103 104 /** 105 * Return the access point Multi-Link Device (MLD) MAC Address for Wi-Fi 7 access points. 106 * i.e. {@link #getWifiStandard()} returns {@link #WIFI_STANDARD_11BE}. 107 * 108 * @return MLD MAC Address for access point if exists (Wi-Fi 7 access points), null otherwise. 109 */ 110 @Nullable getApMldMacAddress()111 public MacAddress getApMldMacAddress() { 112 return mApMldMacAddress; 113 } 114 115 /** 116 * Set the access point Multi-Link Device (MLD) MAC Address. 117 * @hide 118 */ setApMldMacAddress(@ullable MacAddress address)119 public void setApMldMacAddress(@Nullable MacAddress address) { 120 mApMldMacAddress = address; 121 } 122 123 /** 124 * The Multi-Link Operation (MLO) link id for the access point. 125 * Only applicable for Wi-Fi 7 access points. 126 */ 127 private int mApMloLinkId = MloLink.INVALID_MLO_LINK_ID; 128 129 /** 130 * Return the access point Multi-Link Operation (MLO) link-id for Wi-Fi 7 access points. 131 * i.e. when {@link #getWifiStandard()} returns {@link #WIFI_STANDARD_11BE}, otherwise return 132 * {@link MloLink#INVALID_MLO_LINK_ID}. 133 * 134 * Valid values are 0-15 as described in IEEE 802.11be Specification, section 9.4.2.295b.2. 135 * 136 * @return {@link MloLink#INVALID_MLO_LINK_ID} or a valid value (0-15). 137 */ 138 @IntRange(from = MloLink.INVALID_MLO_LINK_ID, to = MloLink.MAX_MLO_LINK_ID) getApMloLinkId()139 public int getApMloLinkId() { 140 return mApMloLinkId; 141 } 142 143 /** 144 * Sets the access point Multi-Link Operation (MLO) link-id 145 * @hide 146 */ setApMloLinkId(int linkId)147 public void setApMloLinkId(int linkId) { 148 mApMloLinkId = linkId; 149 } 150 151 /** 152 * The Multi-Link Operation (MLO) affiliated Links. 153 * Only applicable for Wi-Fi 7 access points. 154 * Note: the list of links includes the access point for this ScanResult. 155 */ 156 private List<MloLink> mAffiliatedMloLinks = Collections.emptyList(); 157 158 /** 159 * Return the Multi-Link Operation (MLO) affiliated Links for Wi-Fi 7 access points. 160 * i.e. when {@link #getWifiStandard()} returns {@link #WIFI_STANDARD_11BE}. 161 * 162 * @return List of affiliated MLO links, or an empty list if access point is not Wi-Fi 7 163 */ 164 @NonNull getAffiliatedMloLinks()165 public List<MloLink> getAffiliatedMloLinks() { 166 return new ArrayList<MloLink>(mAffiliatedMloLinks); 167 } 168 169 /** 170 * Set the Multi-Link Operation (MLO) affiliated Links. 171 * Only applicable for Wi-Fi 7 access points. 172 * 173 * @hide 174 */ setAffiliatedMloLinks(@onNull List<MloLink> links)175 public void setAffiliatedMloLinks(@NonNull List<MloLink> links) { 176 mAffiliatedMloLinks = new ArrayList<MloLink>(links); 177 } 178 179 /** 180 * The HESSID from the beacon. 181 * @hide 182 */ 183 @UnsupportedAppUsage 184 public long hessid; 185 186 /** 187 * The ANQP Domain ID from the Hotspot 2.0 Indication element, if present. 188 * @hide 189 */ 190 @UnsupportedAppUsage 191 public int anqpDomainId; 192 193 /* 194 * This field is equivalent to the |flags|, rather than the |capabilities| field 195 * of the per-BSS scan results returned by WPA supplicant. See the definition of 196 * |struct wpa_bss| in wpa_supplicant/bss.h for more details. 197 */ 198 /** 199 * Describes the authentication, key management, and encryption schemes 200 * supported by the access point. 201 */ 202 public String capabilities; 203 204 /** 205 * The interface name on which the scan result was received. 206 * @hide 207 */ 208 public String ifaceName; 209 210 /** 211 * @hide 212 * No security protocol. 213 */ 214 @SystemApi 215 public static final int PROTOCOL_NONE = 0; 216 /** 217 * @hide 218 * Security protocol type: WPA version 1. 219 */ 220 @SystemApi 221 public static final int PROTOCOL_WPA = 1; 222 /** 223 * @hide 224 * Security protocol type: RSN, for WPA version 2, and version 3. 225 */ 226 @SystemApi 227 public static final int PROTOCOL_RSN = 2; 228 /** 229 * @hide 230 * Security protocol type: 231 * OSU Server-only authenticated layer 2 Encryption Network. 232 * Used for Hotspot 2.0. 233 */ 234 @SystemApi 235 public static final int PROTOCOL_OSEN = 3; 236 237 /** 238 * @hide 239 * Security protocol type: WAPI. 240 */ 241 @SystemApi 242 public static final int PROTOCOL_WAPI = 4; 243 244 /** 245 * @hide 246 * No security key management scheme. 247 */ 248 @SystemApi 249 public static final int KEY_MGMT_NONE = 0; 250 /** 251 * @hide 252 * Security key management scheme: PSK. 253 */ 254 @SystemApi 255 public static final int KEY_MGMT_PSK = 1; 256 /** 257 * @hide 258 * Security key management scheme: EAP. 259 */ 260 @SystemApi 261 public static final int KEY_MGMT_EAP = 2; 262 /** 263 * @hide 264 * Security key management scheme: FT_PSK. 265 */ 266 @SystemApi 267 public static final int KEY_MGMT_FT_PSK = 3; 268 /** 269 * @hide 270 * Security key management scheme: FT_EAP. 271 */ 272 @SystemApi 273 public static final int KEY_MGMT_FT_EAP = 4; 274 /** 275 * @hide 276 * Security key management scheme: PSK_SHA256 277 */ 278 @SystemApi 279 public static final int KEY_MGMT_PSK_SHA256 = 5; 280 /** 281 * @hide 282 * Security key management scheme: EAP_SHA256. 283 */ 284 @SystemApi 285 public static final int KEY_MGMT_EAP_SHA256 = 6; 286 /** 287 * @hide 288 * Security key management scheme: OSEN. 289 * Used for Hotspot 2.0. 290 */ 291 @SystemApi 292 public static final int KEY_MGMT_OSEN = 7; 293 /** 294 * @hide 295 * Security key management scheme: SAE. 296 */ 297 @SystemApi 298 public static final int KEY_MGMT_SAE = 8; 299 /** 300 * @hide 301 * Security key management scheme: OWE. 302 */ 303 @SystemApi 304 public static final int KEY_MGMT_OWE = 9; 305 /** 306 * @hide 307 * Security key management scheme: SUITE_B_192. 308 */ 309 @SystemApi 310 public static final int KEY_MGMT_EAP_SUITE_B_192 = 10; 311 /** 312 * @hide 313 * Security key management scheme: FT_SAE. 314 */ 315 @SystemApi 316 public static final int KEY_MGMT_FT_SAE = 11; 317 /** 318 * @hide 319 * Security key management scheme: OWE in transition mode. 320 */ 321 @SystemApi 322 public static final int KEY_MGMT_OWE_TRANSITION = 12; 323 /** 324 * @hide 325 * Security key management scheme: WAPI_PSK. 326 */ 327 @SystemApi 328 public static final int KEY_MGMT_WAPI_PSK = 13; 329 /** 330 * @hide 331 * Security key management scheme: WAPI_CERT. 332 */ 333 @SystemApi 334 public static final int KEY_MGMT_WAPI_CERT = 14; 335 336 /** 337 * @hide 338 * Security key management scheme: FILS_SHA256. 339 */ 340 public static final int KEY_MGMT_FILS_SHA256 = 15; 341 /** 342 * @hide 343 * Security key management scheme: FILS_SHA384. 344 */ 345 public static final int KEY_MGMT_FILS_SHA384 = 16; 346 /** 347 * @hide 348 * Security key management scheme: DPP. 349 */ 350 public static final int KEY_MGMT_DPP = 17; 351 /** 352 * @hide 353 * Security key management scheme: SAE_EXT_KEY. 354 */ 355 public static final int KEY_MGMT_SAE_EXT_KEY = 18; 356 /** 357 * @hide 358 * Security key management scheme: FT_SAE_EXT_KEY. 359 */ 360 public static final int KEY_MGMT_FT_SAE_EXT_KEY = 19; 361 /** 362 * @hide 363 * Security key management scheme: any unknown AKM. 364 */ 365 public static final int KEY_MGMT_UNKNOWN = 20; 366 /** 367 * @hide 368 * No cipher suite. 369 */ 370 @SystemApi 371 public static final int CIPHER_NONE = 0; 372 /** 373 * @hide 374 * No group addressed, only used for group data cipher. 375 */ 376 @SystemApi 377 public static final int CIPHER_NO_GROUP_ADDRESSED = 1; 378 /** 379 * @hide 380 * Cipher suite: TKIP 381 */ 382 @SystemApi 383 public static final int CIPHER_TKIP = 2; 384 /** 385 * @hide 386 * Cipher suite: CCMP 387 */ 388 @SystemApi 389 public static final int CIPHER_CCMP = 3; 390 /** 391 * @hide 392 * Cipher suite: GCMP 393 */ 394 @SystemApi 395 public static final int CIPHER_GCMP_256 = 4; 396 /** 397 * @hide 398 * Cipher suite: SMS4 399 */ 400 @SystemApi 401 public static final int CIPHER_SMS4 = 5; 402 /** 403 * @hide 404 * Cipher suite: GCMP_128 405 */ 406 @SystemApi 407 public static final int CIPHER_GCMP_128 = 6; 408 /** 409 * @hide 410 * Cipher suite: BIP_GMAC_128 411 */ 412 @SystemApi 413 public static final int CIPHER_BIP_GMAC_128 = 7; 414 /** 415 * @hide 416 * Cipher suite: BIP_GMAC_256 417 */ 418 @SystemApi 419 public static final int CIPHER_BIP_GMAC_256 = 8; 420 /** 421 * @hide 422 * Cipher suite: BIP_CMAC_256 423 */ 424 @SystemApi 425 public static final int CIPHER_BIP_CMAC_256 = 9; 426 427 /** 428 * The detected signal level in dBm, also known as the RSSI. 429 * 430 * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into 431 * an absolute signal level which can be displayed to a user. 432 */ 433 public int level; 434 435 /** 436 * The center frequency of the primary 20 MHz frequency (in MHz) of the channel over which the 437 * client is communicating with the access point. 438 */ 439 public int frequency; 440 441 /** 442 * AP Channel bandwidth is 20 MHZ 443 */ 444 public static final int CHANNEL_WIDTH_20MHZ = 0; 445 /** 446 * AP Channel bandwidth is 40 MHZ 447 */ 448 public static final int CHANNEL_WIDTH_40MHZ = 1; 449 /** 450 * AP Channel bandwidth is 80 MHZ 451 */ 452 public static final int CHANNEL_WIDTH_80MHZ = 2; 453 /** 454 * AP Channel bandwidth is 160 MHZ 455 */ 456 public static final int CHANNEL_WIDTH_160MHZ = 3; 457 /** 458 * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ 459 */ 460 public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; 461 /** 462 * AP Channel bandwidth is 320 MHZ 463 */ 464 public static final int CHANNEL_WIDTH_320MHZ = 5; 465 466 /** 467 * Preamble type: Legacy. 468 */ 469 public static final int PREAMBLE_LEGACY = 0; 470 /** 471 * Preamble type: HT. 472 */ 473 public static final int PREAMBLE_HT = 1; 474 /** 475 * Preamble type: VHT. 476 */ 477 public static final int PREAMBLE_VHT = 2; 478 /** 479 * Preamble type: HE. 480 */ 481 public static final int PREAMBLE_HE = 3; 482 483 /** 484 * Preamble type: EHT. 485 */ 486 public static final int PREAMBLE_EHT = 4; 487 488 /** 489 * Wi-Fi unknown standard 490 */ 491 public static final int WIFI_STANDARD_UNKNOWN = 0; 492 493 /** 494 * Wi-Fi 802.11a/b/g 495 */ 496 public static final int WIFI_STANDARD_LEGACY = 1; 497 498 /** 499 * Wi-Fi 802.11n 500 */ 501 public static final int WIFI_STANDARD_11N = 4; 502 503 /** 504 * Wi-Fi 802.11ac 505 */ 506 public static final int WIFI_STANDARD_11AC = 5; 507 508 /** 509 * Wi-Fi 802.11ax 510 */ 511 public static final int WIFI_STANDARD_11AX = 6; 512 513 /** 514 * Wi-Fi 802.11ad 515 */ 516 public static final int WIFI_STANDARD_11AD = 7; 517 518 /** 519 * Wi-Fi 802.11be 520 */ 521 public static final int WIFI_STANDARD_11BE = 8; 522 523 /** 524 * Wi-Fi 2.4 GHz band. 525 */ 526 public static final int WIFI_BAND_24_GHZ = WifiScanner.WIFI_BAND_24_GHZ; 527 528 /** 529 * Wi-Fi 5 GHz band. 530 */ 531 public static final int WIFI_BAND_5_GHZ = WifiScanner.WIFI_BAND_5_GHZ; 532 533 /** 534 * Wi-Fi 6 GHz band. 535 */ 536 public static final int WIFI_BAND_6_GHZ = WifiScanner.WIFI_BAND_6_GHZ; 537 538 /** 539 * Wi-Fi 60 GHz band. 540 */ 541 public static final int WIFI_BAND_60_GHZ = WifiScanner.WIFI_BAND_60_GHZ; 542 543 /** 544 * Constant used for dual 5GHz multi-internet use-case only. Not to be used for regular scan 545 * result reporting. 546 * @hide 547 */ 548 public static final int WIFI_BAND_5_GHZ_LOW = WifiScanner.WIFI_BAND_5_GHZ_LOW; 549 550 /** 551 * Constant used for dual 5GHz multi-internet use-case only. Not to be used for regular scan 552 * result reporting. 553 * @hide 554 */ 555 public static final int WIFI_BAND_5_GHZ_HIGH = WifiScanner.WIFI_BAND_5_GHZ_HIGH; 556 557 /** 558 * @hide 559 */ 560 @Retention(RetentionPolicy.SOURCE) 561 @IntDef(prefix = {"WIFI_BAND_"}, value = { 562 UNSPECIFIED, 563 WIFI_BAND_24_GHZ, 564 WIFI_BAND_5_GHZ, 565 WIFI_BAND_6_GHZ, 566 WIFI_BAND_60_GHZ}) 567 public @interface WifiBand {}; 568 569 /** 570 * AP wifi standard. 571 */ 572 private @WifiStandard int mWifiStandard = WIFI_STANDARD_UNKNOWN; 573 574 /** 575 * return the AP wifi standard. 576 */ getWifiStandard()577 public @WifiStandard int getWifiStandard() { 578 return mWifiStandard; 579 } 580 581 /** 582 * sets the AP wifi standard. 583 * @hide 584 */ setWifiStandard(@ifiStandard int standard)585 public void setWifiStandard(@WifiStandard int standard) { 586 mWifiStandard = standard; 587 } 588 589 /** 590 * Convert Wi-Fi standard to string 591 * @hide 592 */ wifiStandardToString(@ifiStandard int standard)593 public static @Nullable String wifiStandardToString(@WifiStandard int standard) { 594 switch(standard) { 595 case WIFI_STANDARD_LEGACY: 596 return "legacy"; 597 case WIFI_STANDARD_11N: 598 return "11n"; 599 case WIFI_STANDARD_11AC: 600 return "11ac"; 601 case WIFI_STANDARD_11AX: 602 return "11ax"; 603 case WIFI_STANDARD_11AD: 604 return "11ad"; 605 case WIFI_STANDARD_11BE: 606 return "11be"; 607 case WIFI_STANDARD_UNKNOWN: 608 return "unknown"; 609 } 610 return null; 611 } 612 613 /** 614 * AP Channel bandwidth; one of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ}, 615 * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ}, {@link #CHANNEL_WIDTH_320MHZ}, 616 * or {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}, or {@link #CHANNEL_WIDTH_320MHZ} 617 */ 618 public @ChannelWidth int channelWidth; 619 620 /** 621 * Not used if the AP bandwidth is 20 MHz 622 * If the AP use 40, 80, 160 or 320MHz, this is the center frequency (in MHz) 623 * if the AP use 80 + 80 MHz, this is the center frequency of the first segment (in MHz) 624 */ 625 public int centerFreq0; 626 627 /** 628 * Only used if the AP bandwidth is 80 + 80 MHz 629 * if the AP use 80 + 80 MHz, this is the center frequency of the second segment (in MHz) 630 */ 631 public int centerFreq1; 632 633 /** 634 * @deprecated use is80211mcResponder() instead 635 * @hide 636 */ 637 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 638 public boolean is80211McRTTResponder; 639 640 /** 641 * timestamp in microseconds (since boot) when 642 * this result was last seen. 643 */ 644 public long timestamp; 645 646 /** 647 * Timestamp representing date when this result was last seen, in milliseconds from 1970 648 * {@hide} 649 */ 650 @UnsupportedAppUsage 651 public long seen; 652 653 /** 654 * On devices with multiple hardware radio chains, this class provides metadata about 655 * each radio chain that was used to receive this scan result (probe response or beacon). 656 * {@hide} 657 */ 658 public static class RadioChainInfo { 659 /** Vendor defined id for a radio chain. */ 660 public int id; 661 /** Detected signal level in dBm (also known as the RSSI) on this radio chain. */ 662 public int level; 663 664 @Override toString()665 public String toString() { 666 return "RadioChainInfo: id=" + id + ", level=" + level; 667 } 668 669 @Override equals(Object otherObj)670 public boolean equals(Object otherObj) { 671 if (this == otherObj) { 672 return true; 673 } 674 if (!(otherObj instanceof RadioChainInfo)) { 675 return false; 676 } 677 RadioChainInfo other = (RadioChainInfo) otherObj; 678 return id == other.id && level == other.level; 679 } 680 681 @Override hashCode()682 public int hashCode() { 683 return Objects.hash(id, level); 684 } 685 }; 686 687 /** 688 * Information about the list of the radio chains used to receive this scan result 689 * (probe response or beacon). 690 * 691 * For Example: On devices with 2 hardware radio chains, this list could hold 1 or 2 692 * entries based on whether this scan result was received using one or both the chains. 693 * {@hide} 694 */ 695 public RadioChainInfo[] radioChainInfos; 696 697 /** 698 * Status indicating the scan result does not correspond to a user's saved configuration 699 * @hide 700 * @removed 701 */ 702 @SystemApi 703 public boolean untrusted; 704 705 /** 706 * Number of time autojoin used it 707 * @hide 708 */ 709 @UnsupportedAppUsage 710 public int numUsage; 711 712 /** 713 * The approximate distance to the AP in centimeter, if available. Else 714 * {@link #UNSPECIFIED}. 715 * {@hide} 716 */ 717 @UnsupportedAppUsage 718 public int distanceCm; 719 720 /** 721 * The standard deviation of the distance to the access point, if available. 722 * Else {@link #UNSPECIFIED}. 723 * {@hide} 724 */ 725 @UnsupportedAppUsage 726 public int distanceSdCm; 727 728 /** {@hide} */ 729 public static final long FLAG_PASSPOINT_NETWORK = 0x0000000000000001; 730 731 /** {@hide} */ 732 public static final long FLAG_80211mc_RESPONDER = 0x0000000000000002; 733 734 /** @hide */ 735 public static final long FLAG_80211az_NTB_RESPONDER = 0x0000000000000004; 736 737 /** @hide */ 738 public static final long FLAG_TWT_RESPONDER = 0x0000000000000008; 739 /* 740 * These flags are specific to the ScanResult class, and are not related to the |flags| 741 * field of the per-BSS scan results from WPA supplicant. 742 */ 743 /** 744 * Defines flags; such as {@link #FLAG_PASSPOINT_NETWORK}. 745 * {@hide} 746 */ 747 @UnsupportedAppUsage 748 public long flags; 749 750 /** 751 * sets a flag in {@link #flags} field 752 * @param flag flag to set 753 * @hide 754 */ setFlag(long flag)755 public void setFlag(long flag) { 756 flags |= flag; 757 } 758 759 /** 760 * clears a flag in {@link #flags} field 761 * @param flag flag to set 762 * @hide 763 */ clearFlag(long flag)764 public void clearFlag(long flag) { 765 flags &= ~flag; 766 } 767 is80211mcResponder()768 public boolean is80211mcResponder() { 769 return (flags & FLAG_80211mc_RESPONDER) != 0; 770 } 771 772 /** 773 * @return whether AP is a IEEE802.11az Non-Trigger based Ranging Responder. 774 */ 775 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) is80211azNtbResponder()776 public boolean is80211azNtbResponder() { 777 return (flags & FLAG_80211az_NTB_RESPONDER) != 0; 778 } 779 isPasspointNetwork()780 public boolean isPasspointNetwork() { 781 return (flags & FLAG_PASSPOINT_NETWORK) != 0; 782 } 783 784 /** 785 * @return whether AP is Target Wake Time (TWT) Responder. 786 */ 787 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) isTwtResponder()788 public boolean isTwtResponder() { 789 return (flags & FLAG_TWT_RESPONDER) != 0; 790 } 791 792 /** 793 * Indicates venue name (such as 'San Francisco Airport') published by access point; only 794 * available on Passpoint network and if published by access point. 795 * @deprecated - This information is not provided 796 */ 797 @Deprecated 798 public CharSequence venueName; 799 800 /** 801 * Indicates Passpoint operator name published by access point. 802 * @deprecated - Use {@link WifiInfo#getPasspointProviderFriendlyName()} 803 */ 804 @Deprecated 805 public CharSequence operatorFriendlyName; 806 807 /** 808 * The unspecified value. 809 */ 810 public final static int UNSPECIFIED = -1; 811 812 /** 813 * 2.4 GHz band first channel number 814 * @hide 815 */ 816 public static final int BAND_24_GHZ_FIRST_CH_NUM = 1; 817 /** 818 * 2.4 GHz band last channel number 819 * @hide 820 */ 821 public static final int BAND_24_GHZ_LAST_CH_NUM = 14; 822 /** 823 * 2.4 GHz band frequency of first channel in MHz 824 * @hide 825 */ 826 public static final int BAND_24_GHZ_START_FREQ_MHZ = 2412; 827 /** 828 * 2.4 GHz band frequency of last channel in MHz 829 * @hide 830 */ 831 public static final int BAND_24_GHZ_END_FREQ_MHZ = 2484; 832 833 /** 834 * 5 GHz band first channel number 835 * @hide 836 */ 837 public static final int BAND_5_GHZ_FIRST_CH_NUM = 32; 838 /** 839 * 5 GHz band last channel number 840 * @hide 841 */ 842 public static final int BAND_5_GHZ_LAST_CH_NUM = 177; 843 /** 844 * 5 GHz band frequency of first channel in MHz 845 * @hide 846 */ 847 public static final int BAND_5_GHZ_START_FREQ_MHZ = 5160; 848 /** 849 * 5 GHz band frequency of last channel in MHz 850 * @hide 851 */ 852 public static final int BAND_5_GHZ_END_FREQ_MHZ = 5885; 853 854 /** 855 * 6 GHz band first channel number 856 * @hide 857 */ 858 public static final int BAND_6_GHZ_FIRST_CH_NUM = 1; 859 /** 860 * 6 GHz band last channel number 861 * @hide 862 */ 863 public static final int BAND_6_GHZ_LAST_CH_NUM = 233; 864 /** 865 * 6 GHz band frequency of first channel in MHz 866 * @hide 867 */ 868 public static final int BAND_6_GHZ_START_FREQ_MHZ = 5955; 869 /** 870 * 6 GHz band frequency of last channel in MHz 871 * @hide 872 */ 873 public static final int BAND_6_GHZ_END_FREQ_MHZ = 7115; 874 /** 875 * The center frequency of the first 6Ghz preferred scanning channel, as defined by 876 * IEEE802.11ax draft 7.0 section 26.17.2.3.3. 877 * @hide 878 */ 879 public static final int BAND_6_GHZ_PSC_START_MHZ = 5975; 880 /** 881 * The number of MHz to increment in order to get the next 6Ghz preferred scanning channel 882 * as defined by IEEE802.11ax draft 7.0 section 26.17.2.3.3. 883 * @hide 884 */ 885 public static final int BAND_6_GHZ_PSC_STEP_SIZE_MHZ = 80; 886 887 /** 888 * 6 GHz band operating class 136 channel 2 center frequency in MHz 889 * @hide 890 */ 891 public static final int BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ = 5935; 892 893 /** 894 * 60 GHz band first channel number 895 * @hide 896 */ 897 public static final int BAND_60_GHZ_FIRST_CH_NUM = 1; 898 /** 899 * 60 GHz band last channel number 900 * @hide 901 */ 902 public static final int BAND_60_GHZ_LAST_CH_NUM = 6; 903 /** 904 * 60 GHz band frequency of first channel in MHz 905 * @hide 906 */ 907 public static final int BAND_60_GHZ_START_FREQ_MHZ = 58320; 908 /** 909 * 60 GHz band frequency of last channel in MHz 910 * @hide 911 */ 912 public static final int BAND_60_GHZ_END_FREQ_MHZ = 70200; 913 /** 914 * The highest frequency in 5GHz low 915 * @hide 916 */ 917 public static final int BAND_5_GHZ_LOW_HIGHEST_FREQ_MHZ = 5320; 918 /** 919 * The lowest frequency in 5GHz high 920 * @hide 921 */ 922 public static final int BAND_5_GHZ_HIGH_LOWEST_FREQ_MHZ = 5500; 923 924 /** 925 * Utility function to check if a frequency within 2.4 GHz band 926 * @param freqMhz frequency in MHz 927 * @return true if within 2.4GHz, false otherwise 928 * 929 * @hide 930 */ is24GHz(int freqMhz)931 public static boolean is24GHz(int freqMhz) { 932 return freqMhz >= BAND_24_GHZ_START_FREQ_MHZ && freqMhz <= BAND_24_GHZ_END_FREQ_MHZ; 933 } 934 935 /** 936 * Utility function to check if a frequency within 5 GHz band 937 * @param freqMhz frequency in MHz 938 * @return true if within 5GHz, false otherwise 939 * 940 * @hide 941 */ is5GHz(int freqMhz)942 public static boolean is5GHz(int freqMhz) { 943 return freqMhz >= BAND_5_GHZ_START_FREQ_MHZ && freqMhz <= BAND_5_GHZ_END_FREQ_MHZ; 944 } 945 946 /** 947 * Utility function to check if a frequency within 6 GHz band 948 * @param freqMhz 949 * @return true if within 6GHz, false otherwise 950 * 951 * @hide 952 */ is6GHz(int freqMhz)953 public static boolean is6GHz(int freqMhz) { 954 if (freqMhz == BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ) { 955 return true; 956 } 957 return (freqMhz >= BAND_6_GHZ_START_FREQ_MHZ && freqMhz <= BAND_6_GHZ_END_FREQ_MHZ); 958 } 959 960 /** 961 * Utility function to check if a frequency is 6Ghz PSC channel. 962 * @param freqMhz 963 * @return true if the frequency is 6GHz PSC, false otherwise 964 * 965 * @hide 966 */ is6GHzPsc(int freqMhz)967 public static boolean is6GHzPsc(int freqMhz) { 968 if (!ScanResult.is6GHz(freqMhz)) { 969 return false; 970 } 971 return (freqMhz - BAND_6_GHZ_PSC_START_MHZ) % BAND_6_GHZ_PSC_STEP_SIZE_MHZ == 0; 972 } 973 974 /** 975 * Utility function to check if a frequency within 60 GHz band 976 * @param freqMhz 977 * @return true if within 60GHz, false otherwise 978 * 979 * @hide 980 */ is60GHz(int freqMhz)981 public static boolean is60GHz(int freqMhz) { 982 return freqMhz >= BAND_60_GHZ_START_FREQ_MHZ && freqMhz <= BAND_60_GHZ_END_FREQ_MHZ; 983 } 984 985 /** 986 * Utility function to check whether 2 frequencies are valid for multi-internet connection 987 * when dual-5GHz is supported. 988 * 989 * The allowed combinations are: 990 * - 2.4GHz + Any 5GHz 991 * - 2.4GHz + 6Ghz 992 * - 5GHz low + 5GHz high 993 * - 5GHz low + 6GHz 994 * @hide 995 */ isValidCombinedBandForDual5GHz(int freqMhz1, int freqMhz2)996 public static boolean isValidCombinedBandForDual5GHz(int freqMhz1, int freqMhz2) { 997 int band1 = toBand(freqMhz1); 998 int band2 = toBand(freqMhz2); 999 if (band1 == WIFI_BAND_24_GHZ || band2 == WIFI_BAND_24_GHZ) { 1000 return band1 != band2; 1001 } 1002 1003 // 5GHz Low : b1 36-48 b2 52-64(5320) 1004 // 5GHz High : b3 100(5500)-144 b4 149-165 1005 if ((freqMhz1 <= BAND_5_GHZ_LOW_HIGHEST_FREQ_MHZ 1006 && freqMhz2 >= BAND_5_GHZ_HIGH_LOWEST_FREQ_MHZ) 1007 || (freqMhz2 <= BAND_5_GHZ_LOW_HIGHEST_FREQ_MHZ 1008 && freqMhz1 >= BAND_5_GHZ_HIGH_LOWEST_FREQ_MHZ)) { 1009 return true; 1010 } 1011 return false; 1012 } 1013 1014 /** 1015 * Utility function to convert Wi-Fi channel number to frequency in MHz. 1016 * 1017 * Reference the Wi-Fi channel numbering and the channelization in IEEE 802.11-2016 1018 * specifications, section 17.3.8.4.2, 17.3.8.4.3 and Table 15-6. 1019 * 1020 * See also {@link #convertFrequencyMhzToChannelIfSupported(int)}. 1021 * 1022 * @param channel number to convert. 1023 * @param band of channel to convert. One of the following bands: 1024 * {@link #WIFI_BAND_24_GHZ}, {@link #WIFI_BAND_5_GHZ}, 1025 * {@link #WIFI_BAND_6_GHZ}, {@link #WIFI_BAND_60_GHZ}. 1026 * @return center frequency in Mhz of the channel, {@link #UNSPECIFIED} if no match 1027 */ convertChannelToFrequencyMhzIfSupported(int channel, @WifiBand int band)1028 public static int convertChannelToFrequencyMhzIfSupported(int channel, @WifiBand int band) { 1029 if (band == WIFI_BAND_24_GHZ) { 1030 // Special case 1031 if (channel == 14) { 1032 return 2484; 1033 } else if (channel >= BAND_24_GHZ_FIRST_CH_NUM && channel <= BAND_24_GHZ_LAST_CH_NUM) { 1034 return ((channel - BAND_24_GHZ_FIRST_CH_NUM) * 5) + BAND_24_GHZ_START_FREQ_MHZ; 1035 } else { 1036 return UNSPECIFIED; 1037 } 1038 } 1039 if (band == WIFI_BAND_5_GHZ) { 1040 if (channel >= BAND_5_GHZ_FIRST_CH_NUM && channel <= BAND_5_GHZ_LAST_CH_NUM) { 1041 return ((channel - BAND_5_GHZ_FIRST_CH_NUM) * 5) + BAND_5_GHZ_START_FREQ_MHZ; 1042 } else { 1043 return UNSPECIFIED; 1044 } 1045 } 1046 if (band == WIFI_BAND_6_GHZ) { 1047 if (channel >= BAND_6_GHZ_FIRST_CH_NUM && channel <= BAND_6_GHZ_LAST_CH_NUM) { 1048 if (channel == 2) { 1049 return BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ; 1050 } 1051 return ((channel - BAND_6_GHZ_FIRST_CH_NUM) * 5) + BAND_6_GHZ_START_FREQ_MHZ; 1052 } else { 1053 return UNSPECIFIED; 1054 } 1055 } 1056 if (band == WIFI_BAND_60_GHZ) { 1057 if (channel >= BAND_60_GHZ_FIRST_CH_NUM && channel <= BAND_60_GHZ_LAST_CH_NUM) { 1058 return ((channel - BAND_60_GHZ_FIRST_CH_NUM) * 2160) + BAND_60_GHZ_START_FREQ_MHZ; 1059 } else { 1060 return UNSPECIFIED; 1061 } 1062 } 1063 return UNSPECIFIED; 1064 } 1065 1066 /** 1067 * Utility function to convert Operating Class into a band 1068 * 1069 * Use 802.11 Specification Table E-4: Global Operating Classes for decoding 1070 * 1071 * @param opClass operating class 1072 * @param channel number 1073 * 1074 * @return one of {@link WifiScanner.WIFI_BAND_24_GHZ}, {@link WifiScanner.WIFI_BAND_5_GHZ}, or 1075 * {@link WifiScanner.WIFI_BAND_6_GHZ} for a valid opClass, channel pair, otherwise 1076 * {@link WifiScanner.WIFI_BAND_UNSPECIFIED} is returned. 1077 * 1078 * @hide 1079 */ getBandFromOpClass(int opClass, int channel)1080 public static int getBandFromOpClass(int opClass, int channel) { 1081 if (opClass >= 81 && opClass <= 84) { 1082 if (channel >= BAND_24_GHZ_FIRST_CH_NUM && channel <= BAND_24_GHZ_LAST_CH_NUM) { 1083 return WifiScanner.WIFI_BAND_24_GHZ; 1084 } 1085 } else if (opClass >= 115 && opClass <= 130) { 1086 if (channel >= BAND_5_GHZ_FIRST_CH_NUM && channel <= BAND_5_GHZ_LAST_CH_NUM) { 1087 return WifiScanner.WIFI_BAND_5_GHZ; 1088 } 1089 } else if (opClass >= 131 && opClass <= 137) { 1090 if (channel >= BAND_6_GHZ_FIRST_CH_NUM && channel <= BAND_6_GHZ_LAST_CH_NUM) { 1091 return WifiScanner.WIFI_BAND_6_GHZ; 1092 } 1093 } 1094 1095 // If none of the above combinations, then return as invalid band 1096 return WifiScanner.WIFI_BAND_UNSPECIFIED; 1097 } 1098 1099 /** 1100 * Utility function to convert frequency in MHz to channel number. 1101 * 1102 * See also {@link #convertChannelToFrequencyMhzIfSupported(int, int)}. 1103 * 1104 * @param freqMhz frequency in MHz 1105 * @return channel number associated with given frequency, {@link #UNSPECIFIED} if no match 1106 */ convertFrequencyMhzToChannelIfSupported(int freqMhz)1107 public static int convertFrequencyMhzToChannelIfSupported(int freqMhz) { 1108 // Special case 1109 if (freqMhz == 2484) { 1110 return 14; 1111 } else if (is24GHz(freqMhz)) { 1112 return (freqMhz - BAND_24_GHZ_START_FREQ_MHZ) / 5 + BAND_24_GHZ_FIRST_CH_NUM; 1113 } else if (is5GHz(freqMhz)) { 1114 return ((freqMhz - BAND_5_GHZ_START_FREQ_MHZ) / 5) + BAND_5_GHZ_FIRST_CH_NUM; 1115 } else if (is6GHz(freqMhz)) { 1116 if (freqMhz == BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ) { 1117 return 2; 1118 } 1119 return ((freqMhz - BAND_6_GHZ_START_FREQ_MHZ) / 5) + BAND_6_GHZ_FIRST_CH_NUM; 1120 } else if (is60GHz(freqMhz)) { 1121 return ((freqMhz - BAND_60_GHZ_START_FREQ_MHZ) / 2160) + BAND_60_GHZ_FIRST_CH_NUM; 1122 } 1123 1124 return UNSPECIFIED; 1125 } 1126 1127 /** 1128 * Returns the band for the ScanResult according to its frequency. 1129 * @hide 1130 */ toBand(int frequency)1131 @WifiBand public static int toBand(int frequency) { 1132 if (ScanResult.is24GHz(frequency)) { 1133 return ScanResult.WIFI_BAND_24_GHZ; 1134 } else if (ScanResult.is5GHz(frequency)) { 1135 return ScanResult.WIFI_BAND_5_GHZ; 1136 } else if (ScanResult.is6GHz(frequency)) { 1137 return ScanResult.WIFI_BAND_6_GHZ; 1138 } else if (ScanResult.is60GHz(frequency)) { 1139 return ScanResult.WIFI_BAND_60_GHZ; 1140 } 1141 return ScanResult.UNSPECIFIED; 1142 } 1143 1144 /** 1145 * Returns the band for the ScanResult according to its frequency. 1146 * @hide 1147 */ 1148 @SystemApi getBand()1149 @WifiBand public int getBand() { 1150 return ScanResult.toBand(this.frequency); 1151 } 1152 1153 /** 1154 * @hide 1155 */ is24GHz()1156 public boolean is24GHz() { 1157 return ScanResult.is24GHz(frequency); 1158 } 1159 1160 /** 1161 * @hide 1162 */ is5GHz()1163 public boolean is5GHz() { 1164 return ScanResult.is5GHz(frequency); 1165 } 1166 1167 /** 1168 * @hide 1169 */ is6GHz()1170 public boolean is6GHz() { 1171 return ScanResult.is6GHz(frequency); 1172 } 1173 1174 /** 1175 * @hide 1176 */ is6GhzPsc()1177 public boolean is6GhzPsc() { 1178 return ScanResult.is6GHzPsc(frequency); 1179 } 1180 1181 /** 1182 * @hide 1183 */ is60GHz()1184 public boolean is60GHz() { 1185 return ScanResult.is60GHz(frequency); 1186 } 1187 1188 /** 1189 * @hide 1190 * anqp lines from supplicant BSS response 1191 */ 1192 @UnsupportedAppUsage 1193 public List<String> anqpLines; 1194 1195 /** 1196 * information elements from beacon. 1197 */ 1198 public static class InformationElement implements Parcelable { 1199 /** @hide */ 1200 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1201 public static final int EID_SSID = 0; 1202 /** @hide */ 1203 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1204 public static final int EID_SUPPORTED_RATES = 1; 1205 /** @hide */ 1206 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1207 public static final int EID_TIM = 5; 1208 /** @hide */ 1209 public static final int EID_COUNTRY = 7; 1210 /** @hide */ 1211 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1212 public static final int EID_BSS_LOAD = 11; 1213 /** @hide */ 1214 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1215 public static final int EID_ERP = 42; 1216 /** @hide */ 1217 public static final int EID_HT_CAPABILITIES = 45; 1218 /** @hide */ 1219 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1220 public static final int EID_RSN = 48; 1221 /** @hide */ 1222 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1223 public static final int EID_EXTENDED_SUPPORTED_RATES = 50; 1224 /** @hide */ 1225 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1226 public static final int EID_HT_OPERATION = 61; 1227 /** @hide */ 1228 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1229 public static final int EID_INTERWORKING = 107; 1230 /** @hide */ 1231 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1232 public static final int EID_ROAMING_CONSORTIUM = 111; 1233 /** @hide */ 1234 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1235 public static final int EID_EXTENDED_CAPS = 127; 1236 /** @hide */ 1237 public static final int EID_VHT_CAPABILITIES = 191; 1238 /** @hide */ 1239 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1240 public static final int EID_VHT_OPERATION = 192; 1241 /** @hide */ 1242 public static final int EID_RNR = 201; 1243 /** @hide */ 1244 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 1245 public static final int EID_VSA = 221; 1246 /** @hide */ 1247 public static final int EID_EXTENSION_PRESENT = 255; 1248 1249 // Extension IDs 1250 /** @hide */ 1251 public static final int EID_EXT_HE_CAPABILITIES = 35; 1252 /** @hide */ 1253 public static final int EID_EXT_HE_OPERATION = 36; 1254 /** 1255 * EHT Operation IE extension id: see IEEE 802.11be Specification section 9.4.2.1 1256 * 1257 * @hide 1258 */ 1259 public static final int EID_EXT_EHT_OPERATION = 106; 1260 /** 1261 * Multi-Link IE extension id: see IEEE 802.11be Specification section 9.4.2.1 1262 * 1263 * @hide 1264 */ 1265 public static final int EID_EXT_MULTI_LINK = 107; 1266 /** 1267 * Multi-Link IE Fragment sub element ID: see IEEE 802.11be Specification section 9.4.2.312 1268 * Multi-Link element. 1269 * 1270 * @hide 1271 */ 1272 public static final int EID_FRAGMENT_SUB_ELEMENT_MULTI_LINK = 254; 1273 1274 /** 1275 * EHT Capabilities IE extension id: see IEEE 802.11be Specification section 9.4.2.1 1276 * 1277 * @hide 1278 */ 1279 public static final int EID_EXT_EHT_CAPABILITIES = 108; 1280 1281 /** @hide */ 1282 @UnsupportedAppUsage 1283 public int id; 1284 /** @hide */ 1285 public int idExt; 1286 1287 /** @hide */ 1288 @UnsupportedAppUsage 1289 public byte[] bytes; 1290 1291 /** @hide */ InformationElement()1292 public InformationElement() { 1293 } 1294 1295 /** 1296 * Constructs InformationElements from beacon. 1297 * 1298 * @param id element id 1299 * @param idExt element id extension 1300 * @param bytes the body of the information element, may contain multiple elements 1301 */ InformationElement(int id, int idExt, @NonNull byte[] bytes)1302 public InformationElement(int id, int idExt, @NonNull byte[] bytes) { 1303 this.id = id; 1304 this.idExt = idExt; 1305 this.bytes = bytes.clone(); 1306 } 1307 InformationElement(@onNull InformationElement rhs)1308 public InformationElement(@NonNull InformationElement rhs) { 1309 this.id = rhs.id; 1310 this.idExt = rhs.idExt; 1311 this.bytes = rhs.bytes.clone(); 1312 } 1313 1314 /** 1315 * The element ID of the information element. Defined in the IEEE 802.11-2016 spec 1316 * Table 9-77. 1317 */ getId()1318 public int getId() { 1319 return id; 1320 } 1321 1322 /** 1323 * The element ID Extension of the information element. Defined in the IEEE 802.11-2016 spec 1324 * Table 9-77. 1325 */ getIdExt()1326 public int getIdExt() { 1327 return idExt; 1328 } 1329 1330 /** 1331 * Get the specific content of the information element. 1332 */ 1333 @NonNull getBytes()1334 public ByteBuffer getBytes() { 1335 return ByteBuffer.wrap(bytes).asReadOnlyBuffer(); 1336 } 1337 1338 /** Implement the Parcelable interface {@hide} */ describeContents()1339 public int describeContents() { 1340 return 0; 1341 } 1342 1343 /** Implement the Parcelable interface {@hide} */ writeToParcel(Parcel dest, int flags)1344 public void writeToParcel(Parcel dest, int flags) { 1345 dest.writeInt(id); 1346 dest.writeInt(idExt); 1347 dest.writeByteArray(bytes); 1348 } 1349 1350 /** Implement the Parcelable interface */ 1351 public static final @NonNull Creator<InformationElement> CREATOR = 1352 new Creator<InformationElement>() { 1353 public InformationElement createFromParcel(Parcel in) { 1354 InformationElement informationElement = new InformationElement(); 1355 informationElement.id = in.readInt(); 1356 informationElement.idExt = in.readInt(); 1357 informationElement.bytes = in.createByteArray(); 1358 return informationElement; 1359 } 1360 1361 public InformationElement[] newArray(int size) { 1362 return new InformationElement[size]; 1363 } 1364 }; 1365 1366 @Override equals(Object that)1367 public boolean equals(Object that) { 1368 if (this == that) return true; 1369 1370 // Potential API behavior change, so don't change behavior on older devices. 1371 if (!SdkLevel.isAtLeastS()) return false; 1372 1373 if (!(that instanceof InformationElement)) return false; 1374 1375 InformationElement thatIE = (InformationElement) that; 1376 return id == thatIE.id 1377 && idExt == thatIE.idExt 1378 && Arrays.equals(bytes, thatIE.bytes); 1379 } 1380 1381 @Override hashCode()1382 public int hashCode() { 1383 // Potential API behavior change, so don't change behavior on older devices. 1384 if (!SdkLevel.isAtLeastS()) return System.identityHashCode(this); 1385 1386 return Objects.hash(id, idExt, Arrays.hashCode(bytes)); 1387 } 1388 } 1389 1390 /** 1391 * information elements found in the beacon. 1392 * @hide 1393 */ 1394 @UnsupportedAppUsage 1395 public InformationElement[] informationElements; 1396 /** 1397 * Get all information elements found in the beacon. 1398 */ 1399 @NonNull getInformationElements()1400 public List<InformationElement> getInformationElements() { 1401 return Collections.unmodifiableList(Arrays.asList(informationElements)); 1402 } 1403 1404 /** 1405 * Get all the security types supported by this ScanResult. 1406 * @return array of {@code WifiInfo#SECURITY_TYPE_*}. 1407 */ 1408 @NonNull getSecurityTypes()1409 public @WifiAnnotations.SecurityType int[] getSecurityTypes() { 1410 List<SecurityParams> params = ScanResultUtil.generateSecurityParamsListFromScanResult(this); 1411 int[] securityTypes = new int[params.size()]; 1412 for (int i = 0; i < securityTypes.length; i++) { 1413 securityTypes[i] = WifiInfo.convertWifiConfigurationSecurityType( 1414 params.get(i).getSecurityType()); 1415 } 1416 return securityTypes; 1417 } 1418 1419 /** ANQP response elements. 1420 * @hide 1421 */ 1422 public AnqpInformationElement[] anqpElements; 1423 1424 /** 1425 * Returns whether a WifiSsid represents a "hidden" SSID of all zero values. 1426 */ isHiddenSsid(@onNull WifiSsid wifiSsid)1427 private boolean isHiddenSsid(@NonNull WifiSsid wifiSsid) { 1428 for (byte b : wifiSsid.getBytes()) { 1429 if (b != 0) { 1430 return false; 1431 } 1432 } 1433 return true; 1434 } 1435 1436 /** 1437 * Builder class used to construct {@link ScanResult} objects. 1438 * 1439 * @hide 1440 */ 1441 public static final class Builder { 1442 private WifiSsid mWifiSsid; 1443 private String mBssid; 1444 private long mHessid = 0; 1445 private int mAnqpDomainId = 0; 1446 private byte[] mOsuProviders = null; 1447 private String mCaps = null; 1448 private int mRssi = UNSPECIFIED; 1449 private int mFrequency = UNSPECIFIED; 1450 private long mTsf = 0; 1451 private int mDistanceCm = UNSPECIFIED; 1452 private int mDistanceSdCm = UNSPECIFIED; 1453 private @ChannelWidth int mChannelWidth = ScanResult.CHANNEL_WIDTH_20MHZ; 1454 private int mCenterFreq0 = UNSPECIFIED; 1455 private int mCenterFreq1 = UNSPECIFIED; 1456 private boolean mIs80211McRTTResponder = false; 1457 private boolean mIs80211azNtbRTTResponder = false; 1458 private boolean mIsTwtResponder = false; 1459 /** @hide */ 1460 @NonNull setHessid(long hessid)1461 public Builder setHessid(long hessid) { 1462 mHessid = hessid; 1463 return this; 1464 } 1465 1466 /** @hide */ 1467 @NonNull setOsuProviders(@ullable byte[] osuProviders)1468 public Builder setOsuProviders(@Nullable byte[] osuProviders) { 1469 mOsuProviders = osuProviders; 1470 return this; 1471 } 1472 1473 /** @hide */ 1474 @NonNull setAnqpDomainId(int anqpDomainId)1475 public Builder setAnqpDomainId(int anqpDomainId) { 1476 mAnqpDomainId = anqpDomainId; 1477 return this; 1478 } 1479 1480 /** @hide */ 1481 @NonNull setCaps(@ullable String caps)1482 public Builder setCaps(@Nullable String caps) { 1483 mCaps = caps; 1484 return this; 1485 } 1486 1487 /** @hide */ 1488 @NonNull setRssi(int rssi)1489 public Builder setRssi(int rssi) { 1490 mRssi = rssi; 1491 return this; 1492 } 1493 1494 /** @hide */ 1495 @NonNull setFrequency(int frequency)1496 public Builder setFrequency(int frequency) { 1497 mFrequency = frequency; 1498 return this; 1499 } 1500 1501 /** @hide */ 1502 @NonNull setTsf(long tsf)1503 public Builder setTsf(long tsf) { 1504 mTsf = tsf; 1505 return this; 1506 } 1507 1508 /** @hide */ 1509 @NonNull setDistanceCm(int distanceCm)1510 public Builder setDistanceCm(int distanceCm) { 1511 mDistanceCm = distanceCm; 1512 return this; 1513 } 1514 1515 /** @hide */ 1516 @NonNull setDistanceSdCm(int distanceSdCm)1517 public Builder setDistanceSdCm(int distanceSdCm) { 1518 mDistanceSdCm = distanceSdCm; 1519 return this; 1520 } 1521 1522 /** @hide */ 1523 @NonNull setChannelWidth(@hannelWidth int channelWidth)1524 public Builder setChannelWidth(@ChannelWidth int channelWidth) { 1525 mChannelWidth = channelWidth; 1526 return this; 1527 } 1528 1529 /** @hide */ 1530 @NonNull setCenterFreq0(int centerFreq0)1531 public Builder setCenterFreq0(int centerFreq0) { 1532 mCenterFreq0 = centerFreq0; 1533 return this; 1534 } 1535 1536 /** @hide */ 1537 @NonNull setCenterFreq1(int centerFreq1)1538 public Builder setCenterFreq1(int centerFreq1) { 1539 mCenterFreq1 = centerFreq1; 1540 return this; 1541 } 1542 1543 /** @hide */ 1544 @NonNull setIs80211McRTTResponder(boolean is80211McRTTResponder)1545 public Builder setIs80211McRTTResponder(boolean is80211McRTTResponder) { 1546 mIs80211McRTTResponder = is80211McRTTResponder; 1547 return this; 1548 } 1549 1550 /** @hide */ 1551 @NonNull setIs80211azNtbRTTResponder(boolean is80211azNtbRTTResponder)1552 public Builder setIs80211azNtbRTTResponder(boolean is80211azNtbRTTResponder) { 1553 mIs80211azNtbRTTResponder = is80211azNtbRTTResponder; 1554 return this; 1555 } 1556 1557 /** @hide */ 1558 @NonNull setIsTwtResponder(boolean isTwtResponder)1559 public Builder setIsTwtResponder(boolean isTwtResponder) { 1560 mIsTwtResponder = isTwtResponder; 1561 return this; 1562 } 1563 1564 /** @hide */ Builder(WifiSsid wifiSsid, String bssid)1565 public Builder(WifiSsid wifiSsid, String bssid) { 1566 mWifiSsid = wifiSsid; 1567 mBssid = bssid; 1568 } 1569 1570 /** 1571 * @hide 1572 * 1573 */ Builder()1574 public Builder() { 1575 1576 } 1577 1578 /** 1579 * @hide 1580 */ setWifiSsid(WifiSsid wifiSsid)1581 public Builder setWifiSsid(WifiSsid wifiSsid) { 1582 mWifiSsid = wifiSsid; 1583 return this; 1584 } 1585 1586 /** 1587 * @hide 1588 */ setBssid(String bssid)1589 public Builder setBssid(String bssid) { 1590 mBssid = bssid; 1591 return this; 1592 } 1593 1594 /** 1595 * @hide 1596 */ clear()1597 public void clear() { 1598 mWifiSsid = null; 1599 mBssid = null; 1600 mHessid = 0; 1601 mAnqpDomainId = 0; 1602 mOsuProviders = null; 1603 mCaps = null; 1604 mRssi = UNSPECIFIED; 1605 mFrequency = UNSPECIFIED; 1606 mTsf = 0; 1607 mDistanceCm = UNSPECIFIED; 1608 mDistanceSdCm = UNSPECIFIED; 1609 mChannelWidth = ScanResult.CHANNEL_WIDTH_20MHZ; 1610 mCenterFreq0 = UNSPECIFIED; 1611 mCenterFreq1 = UNSPECIFIED; 1612 mIs80211McRTTResponder = false; 1613 mIs80211azNtbRTTResponder = false; 1614 mIsTwtResponder = false; 1615 } 1616 1617 /** @hide */ build()1618 public ScanResult build() { 1619 return new ScanResult(this); 1620 } 1621 } 1622 1623 /** 1624 * @hide 1625 */ ScanResult(Builder builder)1626 private ScanResult(Builder builder) { 1627 this.wifiSsid = builder.mWifiSsid; 1628 if (wifiSsid != null && isHiddenSsid(wifiSsid)) { 1629 // Retain the legacy behavior of setting SSID to "" if the SSID is all zero values. 1630 this.SSID = ""; 1631 } else { 1632 final CharSequence utf8Ssid = (wifiSsid != null) ? wifiSsid.getUtf8Text() : null; 1633 this.SSID = (utf8Ssid != null) ? utf8Ssid.toString() : WifiManager.UNKNOWN_SSID; 1634 } 1635 this.BSSID = builder.mBssid; 1636 this.hessid = builder.mHessid; 1637 this.anqpDomainId = builder.mAnqpDomainId; 1638 if (builder.mOsuProviders != null) { 1639 this.anqpElements = new AnqpInformationElement[1]; 1640 this.anqpElements[0] = new AnqpInformationElement( 1641 AnqpInformationElement.HOTSPOT20_VENDOR_ID, 1642 AnqpInformationElement.HS_OSU_PROVIDERS, builder.mOsuProviders); 1643 } 1644 this.capabilities = builder.mCaps; 1645 this.level = builder.mRssi; 1646 this.frequency = builder.mFrequency; 1647 this.timestamp = builder.mTsf; 1648 this.distanceCm = builder.mDistanceCm; 1649 this.distanceSdCm = builder.mDistanceSdCm; 1650 this.channelWidth = builder.mChannelWidth; 1651 this.centerFreq0 = builder.mCenterFreq0; 1652 this.centerFreq1 = builder.mCenterFreq1; 1653 this.flags = 0; 1654 this.flags |= (builder.mIs80211McRTTResponder) ? FLAG_80211mc_RESPONDER : 0; 1655 this.flags |= (builder.mIs80211azNtbRTTResponder) ? FLAG_80211az_NTB_RESPONDER : 0; 1656 this.flags |= (builder.mIsTwtResponder) ? FLAG_TWT_RESPONDER : 0; 1657 this.radioChainInfos = null; 1658 this.mApMldMacAddress = null; 1659 } 1660 1661 /** 1662 * @hide 1663 * @deprecated Use {@link ScanResult.Builder} 1664 */ ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId, byte[] osuProviders, String caps, int level, int frequency, long tsf)1665 public ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId, 1666 byte[] osuProviders, String caps, int level, int frequency, long tsf) { 1667 this.wifiSsid = wifiSsid; 1668 if (wifiSsid != null && isHiddenSsid(wifiSsid)) { 1669 // Retain the legacy behavior of setting SSID to "" if the SSID is all zero values. 1670 this.SSID = ""; 1671 } else { 1672 final CharSequence utf8Ssid = (wifiSsid != null) ? wifiSsid.getUtf8Text() : null; 1673 this.SSID = (utf8Ssid != null) ? utf8Ssid.toString() : WifiManager.UNKNOWN_SSID; 1674 } 1675 this.BSSID = BSSID; 1676 this.hessid = hessid; 1677 this.anqpDomainId = anqpDomainId; 1678 if (osuProviders != null) { 1679 this.anqpElements = new AnqpInformationElement[1]; 1680 this.anqpElements[0] = 1681 new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID, 1682 AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders); 1683 } 1684 this.capabilities = caps; 1685 this.level = level; 1686 this.frequency = frequency; 1687 this.timestamp = tsf; 1688 this.distanceCm = UNSPECIFIED; 1689 this.distanceSdCm = UNSPECIFIED; 1690 this.channelWidth = UNSPECIFIED; 1691 this.centerFreq0 = UNSPECIFIED; 1692 this.centerFreq1 = UNSPECIFIED; 1693 this.flags = 0; 1694 this.radioChainInfos = null; 1695 this.mApMldMacAddress = null; 1696 } 1697 1698 /** 1699 * @hide 1700 * @deprecated Use {@link ScanResult.Builder} 1701 */ ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency, long tsf, int distCm, int distSdCm)1702 public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency, 1703 long tsf, int distCm, int distSdCm) { 1704 this.wifiSsid = wifiSsid; 1705 if (wifiSsid != null && isHiddenSsid(wifiSsid)) { 1706 // Retain the legacy behavior of setting SSID to "" if the SSID is all zero values. 1707 this.SSID = ""; 1708 } else { 1709 final CharSequence utf8Ssid = (wifiSsid != null) ? wifiSsid.getUtf8Text() : null; 1710 this.SSID = (utf8Ssid != null) ? utf8Ssid.toString() : WifiManager.UNKNOWN_SSID; 1711 } 1712 this.BSSID = BSSID; 1713 this.capabilities = caps; 1714 this.level = level; 1715 this.frequency = frequency; 1716 this.timestamp = tsf; 1717 this.distanceCm = distCm; 1718 this.distanceSdCm = distSdCm; 1719 this.channelWidth = UNSPECIFIED; 1720 this.centerFreq0 = UNSPECIFIED; 1721 this.centerFreq1 = UNSPECIFIED; 1722 this.flags = 0; 1723 this.radioChainInfos = null; 1724 this.mApMldMacAddress = null; 1725 } 1726 1727 /** 1728 * @hide 1729 * @deprecated Use {@link ScanResult.Builder} 1730 */ ScanResult(String Ssid, String BSSID, long hessid, int anqpDomainId, String caps, int level, int frequency, long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1, boolean is80211McRTTResponder)1731 public ScanResult(String Ssid, String BSSID, long hessid, int anqpDomainId, String caps, 1732 int level, int frequency, 1733 long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1, 1734 boolean is80211McRTTResponder) { 1735 this.SSID = Ssid; 1736 this.BSSID = BSSID; 1737 this.hessid = hessid; 1738 this.anqpDomainId = anqpDomainId; 1739 this.capabilities = caps; 1740 this.level = level; 1741 this.frequency = frequency; 1742 this.timestamp = tsf; 1743 this.distanceCm = distCm; 1744 this.distanceSdCm = distSdCm; 1745 this.channelWidth = channelWidth; 1746 this.centerFreq0 = centerFreq0; 1747 this.centerFreq1 = centerFreq1; 1748 if (is80211McRTTResponder) { 1749 this.flags = FLAG_80211mc_RESPONDER; 1750 } else { 1751 this.flags = 0; 1752 } 1753 this.radioChainInfos = null; 1754 this.mApMldMacAddress = null; 1755 } 1756 1757 /** 1758 * @hide 1759 * @deprecated Use {@link ScanResult.Builder} 1760 */ ScanResult(WifiSsid wifiSsid, String Ssid, String BSSID, long hessid, int anqpDomainId, String caps, int level, int frequency, long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1, boolean is80211McRTTResponder)1761 public ScanResult(WifiSsid wifiSsid, String Ssid, String BSSID, long hessid, int anqpDomainId, 1762 String caps, int level, 1763 int frequency, long tsf, int distCm, int distSdCm, int channelWidth, 1764 int centerFreq0, int centerFreq1, boolean is80211McRTTResponder) { 1765 this(Ssid, BSSID, hessid, anqpDomainId, caps, level, frequency, tsf, distCm, 1766 distSdCm, channelWidth, centerFreq0, centerFreq1, is80211McRTTResponder); 1767 this.wifiSsid = wifiSsid; 1768 } 1769 1770 /** copy constructor */ ScanResult(@onNull ScanResult source)1771 public ScanResult(@NonNull ScanResult source) { 1772 if (source != null) { 1773 wifiSsid = source.wifiSsid; 1774 SSID = source.SSID; 1775 BSSID = source.BSSID; 1776 hessid = source.hessid; 1777 anqpDomainId = source.anqpDomainId; 1778 informationElements = source.informationElements; 1779 anqpElements = source.anqpElements; 1780 capabilities = source.capabilities; 1781 level = source.level; 1782 frequency = source.frequency; 1783 channelWidth = source.channelWidth; 1784 centerFreq0 = source.centerFreq0; 1785 centerFreq1 = source.centerFreq1; 1786 timestamp = source.timestamp; 1787 distanceCm = source.distanceCm; 1788 distanceSdCm = source.distanceSdCm; 1789 seen = source.seen; 1790 untrusted = source.untrusted; 1791 numUsage = source.numUsage; 1792 venueName = source.venueName; 1793 operatorFriendlyName = source.operatorFriendlyName; 1794 flags = source.flags; 1795 radioChainInfos = source.radioChainInfos; 1796 this.mWifiStandard = source.mWifiStandard; 1797 this.ifaceName = source.ifaceName; 1798 this.mApMldMacAddress = source.mApMldMacAddress; 1799 this.mApMloLinkId = source.mApMloLinkId; 1800 this.mAffiliatedMloLinks = source.mAffiliatedMloLinks != null 1801 ? new ArrayList<>(source.mAffiliatedMloLinks) : Collections.emptyList(); 1802 } 1803 } 1804 1805 /** Construct an empty scan result. */ ScanResult()1806 public ScanResult() { 1807 } 1808 1809 @Override toString()1810 public String toString() { 1811 StringBuffer sb = new StringBuffer(); 1812 String none = "<none>"; 1813 1814 sb.append("SSID: ") 1815 .append(wifiSsid == null ? WifiManager.UNKNOWN_SSID : wifiSsid) 1816 .append(", BSSID: ") 1817 .append(BSSID == null ? none : BSSID) 1818 .append(", capabilities: ") 1819 .append(capabilities == null ? none : capabilities) 1820 .append(", level: ") 1821 .append(level) 1822 .append(", frequency: ") 1823 .append(frequency) 1824 .append(", timestamp: ") 1825 .append(timestamp); 1826 sb.append(", distance: ").append((distanceCm != UNSPECIFIED ? distanceCm : "?")). 1827 append("(cm)"); 1828 sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")). 1829 append("(cm)"); 1830 1831 sb.append(", passpoint: "); 1832 sb.append(((flags & FLAG_PASSPOINT_NETWORK) != 0) ? "yes" : "no"); 1833 sb.append(", ChannelBandwidth: ").append(channelWidth); 1834 sb.append(", centerFreq0: ").append(centerFreq0); 1835 sb.append(", centerFreq1: ").append(centerFreq1); 1836 sb.append(", standard: ").append(wifiStandardToString(mWifiStandard)); 1837 sb.append(", 80211mcResponder: "); 1838 sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported"); 1839 sb.append(", 80211azNtbResponder: "); 1840 sb.append( 1841 ((flags & FLAG_80211az_NTB_RESPONDER) != 0) ? "is supported" : "is not supported"); 1842 sb.append(", TWT Responder: "); 1843 sb.append(((flags & FLAG_TWT_RESPONDER) != 0) ? "yes" : "no"); 1844 sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos)); 1845 sb.append(", interface name: ").append(ifaceName); 1846 1847 if (mApMldMacAddress != null) { 1848 sb.append(", MLO Info: ") 1849 .append(" AP MLD MAC Address: ") 1850 .append(mApMldMacAddress.toString()) 1851 .append(", AP MLO Link-Id: ") 1852 .append((mApMloLinkId == MloLink.INVALID_MLO_LINK_ID) 1853 ? "Unspecified" : mApMloLinkId) 1854 .append(", AP MLO Affiliated Links: ").append(mAffiliatedMloLinks); 1855 } 1856 1857 return sb.toString(); 1858 } 1859 1860 /** Implement the Parcelable interface {@hide} */ describeContents()1861 public int describeContents() { 1862 return 0; 1863 } 1864 1865 /** Implement the Parcelable interface {@hide} */ writeToParcel(Parcel dest, int flags)1866 public void writeToParcel(Parcel dest, int flags) { 1867 long start = dest.dataSize(); 1868 if (wifiSsid != null) { 1869 dest.writeInt(1); 1870 wifiSsid.writeToParcel(dest, flags); 1871 } else { 1872 dest.writeInt(0); 1873 } 1874 dest.writeString(SSID); 1875 dest.writeString(BSSID); 1876 dest.writeLong(hessid); 1877 dest.writeInt(anqpDomainId); 1878 dest.writeString(capabilities); 1879 dest.writeInt(level); 1880 dest.writeInt(frequency); 1881 dest.writeLong(timestamp); 1882 dest.writeInt(distanceCm); 1883 dest.writeInt(distanceSdCm); 1884 dest.writeInt(channelWidth); 1885 dest.writeInt(centerFreq0); 1886 dest.writeInt(centerFreq1); 1887 dest.writeInt(mWifiStandard); 1888 dest.writeLong(seen); 1889 dest.writeInt(untrusted ? 1 : 0); 1890 dest.writeInt(numUsage); 1891 dest.writeString((venueName != null) ? venueName.toString() : ""); 1892 dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : ""); 1893 dest.writeLong(this.flags); 1894 dest.writeTypedArray(informationElements, flags); 1895 1896 if (anqpLines != null) { 1897 dest.writeInt(anqpLines.size()); 1898 for (int i = 0; i < anqpLines.size(); i++) { 1899 dest.writeString(anqpLines.get(i)); 1900 } 1901 } 1902 else { 1903 dest.writeInt(0); 1904 } 1905 int anqpElementsPayloadSize = 0; 1906 if (anqpElements != null) { 1907 dest.writeInt(anqpElements.length); 1908 for (AnqpInformationElement element : anqpElements) { 1909 dest.writeInt(element.getVendorId()); 1910 dest.writeInt(element.getElementId()); 1911 dest.writeInt(element.getPayload().length); 1912 dest.writeByteArray(element.getPayload()); 1913 anqpElementsPayloadSize += element.getPayload().length; 1914 } 1915 } else { 1916 dest.writeInt(0); 1917 } 1918 1919 if (radioChainInfos != null) { 1920 dest.writeInt(radioChainInfos.length); 1921 for (int i = 0; i < radioChainInfos.length; i++) { 1922 dest.writeInt(radioChainInfos[i].id); 1923 dest.writeInt(radioChainInfos[i].level); 1924 } 1925 } else { 1926 dest.writeInt(0); 1927 } 1928 dest.writeString((ifaceName != null) ? ifaceName.toString() : ""); 1929 1930 1931 // Add MLO related attributes 1932 dest.writeParcelable(mApMldMacAddress, flags); 1933 dest.writeInt(mApMloLinkId); 1934 dest.writeTypedList(mAffiliatedMloLinks); 1935 if (dest.dataSize() - start > 10000) { 1936 Log.e( 1937 TAG, 1938 " Abnormal ScanResult: " 1939 + this 1940 + ". The size is " 1941 + (dest.dataSize() - start) 1942 + ". The informationElements size is " 1943 + informationElements.length 1944 + ". The anqpPayload size is " 1945 + anqpElementsPayloadSize); 1946 } 1947 } 1948 1949 /** Implement the Parcelable interface */ 1950 public static final @NonNull Creator<ScanResult> CREATOR = 1951 new Creator<ScanResult>() { 1952 public ScanResult createFromParcel(Parcel in) { 1953 WifiSsid wifiSsid = null; 1954 if (in.readInt() == 1) { 1955 wifiSsid = WifiSsid.CREATOR.createFromParcel(in); 1956 } 1957 ScanResult sr = new ScanResult( 1958 wifiSsid, 1959 in.readString(), /* SSID */ 1960 in.readString(), /* BSSID */ 1961 in.readLong(), /* HESSID */ 1962 in.readInt(), /* ANQP Domain ID */ 1963 in.readString(), /* capabilities */ 1964 in.readInt(), /* level */ 1965 in.readInt(), /* frequency */ 1966 in.readLong(), /* timestamp */ 1967 in.readInt(), /* distanceCm */ 1968 in.readInt(), /* distanceSdCm */ 1969 in.readInt(), /* channelWidth */ 1970 in.readInt(), /* centerFreq0 */ 1971 in.readInt(), /* centerFreq1 */ 1972 false /* rtt responder, 1973 fixed with flags below */ 1974 ); 1975 1976 sr.mWifiStandard = in.readInt(); 1977 sr.seen = in.readLong(); 1978 sr.untrusted = in.readInt() != 0; 1979 sr.numUsage = in.readInt(); 1980 sr.venueName = in.readString(); 1981 sr.operatorFriendlyName = in.readString(); 1982 sr.flags = in.readLong(); 1983 sr.informationElements = in.createTypedArray(InformationElement.CREATOR); 1984 1985 int n = in.readInt(); 1986 if (n != 0) { 1987 sr.anqpLines = new ArrayList<String>(); 1988 for (int i = 0; i < n; i++) { 1989 sr.anqpLines.add(in.readString()); 1990 } 1991 } 1992 n = in.readInt(); 1993 if (n != 0) { 1994 sr.anqpElements = new AnqpInformationElement[n]; 1995 for (int i = 0; i < n; i++) { 1996 int vendorId = in.readInt(); 1997 int elementId = in.readInt(); 1998 int len = in.readInt(); 1999 byte[] payload = new byte[len]; 2000 in.readByteArray(payload); 2001 sr.anqpElements[i] = 2002 new AnqpInformationElement(vendorId, elementId, payload); 2003 } 2004 } 2005 n = in.readInt(); 2006 if (n != 0) { 2007 sr.radioChainInfos = new RadioChainInfo[n]; 2008 for (int i = 0; i < n; i++) { 2009 sr.radioChainInfos[i] = new RadioChainInfo(); 2010 sr.radioChainInfos[i].id = in.readInt(); 2011 sr.radioChainInfos[i].level = in.readInt(); 2012 } 2013 } 2014 sr.ifaceName = in.readString(); 2015 2016 // Read MLO related attributes 2017 sr.mApMldMacAddress = in.readParcelable(MacAddress.class.getClassLoader()); 2018 sr.mApMloLinkId = in.readInt(); 2019 sr.mAffiliatedMloLinks = in.createTypedArrayList(MloLink.CREATOR); 2020 2021 return sr; 2022 } 2023 public ScanResult[] newArray(int size) { 2024 return new ScanResult[size]; 2025 } 2026 }; 2027 } 2028