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