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