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