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.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.SystemApi; 22 import android.compat.annotation.UnsupportedAppUsage; 23 import android.net.wifi.WifiAnnotations.ChannelWidth; 24 import android.net.wifi.WifiAnnotations.WifiStandard; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 28 import java.nio.ByteBuffer; 29 import java.util.ArrayList; 30 import java.util.Arrays; 31 import java.util.Collections; 32 import java.util.List; 33 import java.util.Objects; 34 35 /** 36 * Describes information about a detected access point. In addition 37 * to the attributes described here, the supplicant keeps track of 38 * {@code quality}, {@code noise}, and {@code maxbitrate} attributes, 39 * but does not currently report them to external clients. 40 */ 41 public final class ScanResult implements Parcelable { 42 /** 43 * The network name. 44 */ 45 public String SSID; 46 47 /** 48 * Ascii encoded SSID. This will replace SSID when we deprecate it. @hide 49 */ 50 @UnsupportedAppUsage 51 public WifiSsid wifiSsid; 52 53 /** 54 * The address of the access point. 55 */ 56 public String BSSID; 57 58 /** 59 * The HESSID from the beacon. 60 * @hide 61 */ 62 @UnsupportedAppUsage 63 public long hessid; 64 65 /** 66 * The ANQP Domain ID from the Hotspot 2.0 Indication element, if present. 67 * @hide 68 */ 69 @UnsupportedAppUsage 70 public int anqpDomainId; 71 72 /* 73 * This field is equivalent to the |flags|, rather than the |capabilities| field 74 * of the per-BSS scan results returned by WPA supplicant. See the definition of 75 * |struct wpa_bss| in wpa_supplicant/bss.h for more details. 76 */ 77 /** 78 * Describes the authentication, key management, and encryption schemes 79 * supported by the access point. 80 */ 81 public String capabilities; 82 83 /** 84 * @hide 85 * No security protocol. 86 */ 87 @SystemApi 88 public static final int PROTOCOL_NONE = 0; 89 /** 90 * @hide 91 * Security protocol type: WPA version 1. 92 */ 93 @SystemApi 94 public static final int PROTOCOL_WPA = 1; 95 /** 96 * @hide 97 * Security protocol type: RSN, for WPA version 2, and version 3. 98 */ 99 @SystemApi 100 public static final int PROTOCOL_RSN = 2; 101 /** 102 * @hide 103 * Security protocol type: 104 * OSU Server-only authenticated layer 2 Encryption Network. 105 * Used for Hotspot 2.0. 106 */ 107 @SystemApi 108 public static final int PROTOCOL_OSEN = 3; 109 110 /** 111 * @hide 112 * Security protocol type: WAPI. 113 */ 114 @SystemApi 115 public static final int PROTOCOL_WAPI = 4; 116 117 /** 118 * @hide 119 * No security key management scheme. 120 */ 121 @SystemApi 122 public static final int KEY_MGMT_NONE = 0; 123 /** 124 * @hide 125 * Security key management scheme: PSK. 126 */ 127 @SystemApi 128 public static final int KEY_MGMT_PSK = 1; 129 /** 130 * @hide 131 * Security key management scheme: EAP. 132 */ 133 @SystemApi 134 public static final int KEY_MGMT_EAP = 2; 135 /** 136 * @hide 137 * Security key management scheme: FT_PSK. 138 */ 139 @SystemApi 140 public static final int KEY_MGMT_FT_PSK = 3; 141 /** 142 * @hide 143 * Security key management scheme: FT_EAP. 144 */ 145 @SystemApi 146 public static final int KEY_MGMT_FT_EAP = 4; 147 /** 148 * @hide 149 * Security key management scheme: PSK_SHA256 150 */ 151 @SystemApi 152 public static final int KEY_MGMT_PSK_SHA256 = 5; 153 /** 154 * @hide 155 * Security key management scheme: EAP_SHA256. 156 */ 157 @SystemApi 158 public static final int KEY_MGMT_EAP_SHA256 = 6; 159 /** 160 * @hide 161 * Security key management scheme: OSEN. 162 * Used for Hotspot 2.0. 163 */ 164 @SystemApi 165 public static final int KEY_MGMT_OSEN = 7; 166 /** 167 * @hide 168 * Security key management scheme: SAE. 169 */ 170 @SystemApi 171 public static final int KEY_MGMT_SAE = 8; 172 /** 173 * @hide 174 * Security key management scheme: OWE. 175 */ 176 @SystemApi 177 public static final int KEY_MGMT_OWE = 9; 178 /** 179 * @hide 180 * Security key management scheme: SUITE_B_192. 181 */ 182 @SystemApi 183 public static final int KEY_MGMT_EAP_SUITE_B_192 = 10; 184 /** 185 * @hide 186 * Security key management scheme: FT_SAE. 187 */ 188 @SystemApi 189 public static final int KEY_MGMT_FT_SAE = 11; 190 /** 191 * @hide 192 * Security key management scheme: OWE in transition mode. 193 */ 194 @SystemApi 195 public static final int KEY_MGMT_OWE_TRANSITION = 12; 196 /** 197 * @hide 198 * Security key management scheme: WAPI_PSK. 199 */ 200 @SystemApi 201 public static final int KEY_MGMT_WAPI_PSK = 13; 202 /** 203 * @hide 204 * Security key management scheme: WAPI_CERT. 205 */ 206 @SystemApi 207 public static final int KEY_MGMT_WAPI_CERT = 14; 208 209 /** 210 * @hide 211 * Security key management scheme: FILS_SHA256. 212 */ 213 public static final int KEY_MGMT_FILS_SHA256 = 15; 214 /** 215 * @hide 216 * Security key management scheme: FILS_SHA384. 217 */ 218 public static final int KEY_MGMT_FILS_SHA384 = 16; 219 /** 220 * @hide 221 * No cipher suite. 222 */ 223 @SystemApi 224 public static final int CIPHER_NONE = 0; 225 /** 226 * @hide 227 * No group addressed, only used for group data cipher. 228 */ 229 @SystemApi 230 public static final int CIPHER_NO_GROUP_ADDRESSED = 1; 231 /** 232 * @hide 233 * Cipher suite: TKIP 234 */ 235 @SystemApi 236 public static final int CIPHER_TKIP = 2; 237 /** 238 * @hide 239 * Cipher suite: CCMP 240 */ 241 @SystemApi 242 public static final int CIPHER_CCMP = 3; 243 /** 244 * @hide 245 * Cipher suite: GCMP 246 */ 247 @SystemApi 248 public static final int CIPHER_GCMP_256 = 4; 249 /** 250 * @hide 251 * Cipher suite: SMS4 252 */ 253 @SystemApi 254 public static final int CIPHER_SMS4 = 5; 255 256 /** 257 * The detected signal level in dBm, also known as the RSSI. 258 * 259 * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into 260 * an absolute signal level which can be displayed to a user. 261 */ 262 public int level; 263 /** 264 * The primary 20 MHz frequency (in MHz) of the channel over which the client is communicating 265 * with the access point. 266 */ 267 public int frequency; 268 269 /** 270 * AP Channel bandwidth is 20 MHZ 271 */ 272 public static final int CHANNEL_WIDTH_20MHZ = 0; 273 /** 274 * AP Channel bandwidth is 40 MHZ 275 */ 276 public static final int CHANNEL_WIDTH_40MHZ = 1; 277 /** 278 * AP Channel bandwidth is 80 MHZ 279 */ 280 public static final int CHANNEL_WIDTH_80MHZ = 2; 281 /** 282 * AP Channel bandwidth is 160 MHZ 283 */ 284 public static final int CHANNEL_WIDTH_160MHZ = 3; 285 /** 286 * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ 287 */ 288 public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; 289 290 /** 291 * Wi-Fi unknown standard 292 */ 293 public static final int WIFI_STANDARD_UNKNOWN = 0; 294 295 /** 296 * Wi-Fi 802.11a/b/g 297 */ 298 public static final int WIFI_STANDARD_LEGACY = 1; 299 300 /** 301 * Wi-Fi 802.11n 302 */ 303 public static final int WIFI_STANDARD_11N = 4; 304 305 /** 306 * Wi-Fi 802.11ac 307 */ 308 public static final int WIFI_STANDARD_11AC = 5; 309 310 /** 311 * Wi-Fi 802.11ax 312 */ 313 public static final int WIFI_STANDARD_11AX = 6; 314 315 /** 316 * AP wifi standard. 317 */ 318 private @WifiStandard int mWifiStandard; 319 320 /** 321 * return the AP wifi standard. 322 */ getWifiStandard()323 public @WifiStandard int getWifiStandard() { 324 return mWifiStandard; 325 } 326 327 /** 328 * sets the AP wifi standard. 329 * @hide 330 */ setWifiStandard(@ifiStandard int standard)331 public void setWifiStandard(@WifiStandard int standard) { 332 mWifiStandard = standard; 333 } 334 335 /** 336 * Convert Wi-Fi standard to string 337 */ wifiStandardToString(@ifiStandard int standard)338 private static @Nullable String wifiStandardToString(@WifiStandard int standard) { 339 switch(standard) { 340 case WIFI_STANDARD_LEGACY: 341 return "legacy"; 342 case WIFI_STANDARD_11N: 343 return "11n"; 344 case WIFI_STANDARD_11AC: 345 return "11ac"; 346 case WIFI_STANDARD_11AX: 347 return "11ax"; 348 case WIFI_STANDARD_UNKNOWN: 349 return "unknown"; 350 } 351 return null; 352 } 353 354 /** 355 * AP Channel bandwidth; one of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ}, 356 * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ} 357 * or {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}. 358 */ 359 public @ChannelWidth int channelWidth; 360 361 /** 362 * Not used if the AP bandwidth is 20 MHz 363 * If the AP use 40, 80 or 160 MHz, this is the center frequency (in MHz) 364 * if the AP use 80 + 80 MHz, this is the center frequency of the first segment (in MHz) 365 */ 366 public int centerFreq0; 367 368 /** 369 * Only used if the AP bandwidth is 80 + 80 MHz 370 * if the AP use 80 + 80 MHz, this is the center frequency of the second segment (in MHz) 371 */ 372 public int centerFreq1; 373 374 /** 375 * @deprecated use is80211mcResponder() instead 376 * @hide 377 */ 378 @UnsupportedAppUsage 379 public boolean is80211McRTTResponder; 380 381 /** 382 * timestamp in microseconds (since boot) when 383 * this result was last seen. 384 */ 385 public long timestamp; 386 387 /** 388 * Timestamp representing date when this result was last seen, in milliseconds from 1970 389 * {@hide} 390 */ 391 @UnsupportedAppUsage 392 public long seen; 393 394 /** 395 * On devices with multiple hardware radio chains, this class provides metadata about 396 * each radio chain that was used to receive this scan result (probe response or beacon). 397 * {@hide} 398 */ 399 public static class RadioChainInfo { 400 /** Vendor defined id for a radio chain. */ 401 public int id; 402 /** Detected signal level in dBm (also known as the RSSI) on this radio chain. */ 403 public int level; 404 405 @Override toString()406 public String toString() { 407 return "RadioChainInfo: id=" + id + ", level=" + level; 408 } 409 410 @Override equals(Object otherObj)411 public boolean equals(Object otherObj) { 412 if (this == otherObj) { 413 return true; 414 } 415 if (!(otherObj instanceof RadioChainInfo)) { 416 return false; 417 } 418 RadioChainInfo other = (RadioChainInfo) otherObj; 419 return id == other.id && level == other.level; 420 } 421 422 @Override hashCode()423 public int hashCode() { 424 return Objects.hash(id, level); 425 } 426 }; 427 428 /** 429 * Information about the list of the radio chains used to receive this scan result 430 * (probe response or beacon). 431 * 432 * For Example: On devices with 2 hardware radio chains, this list could hold 1 or 2 433 * entries based on whether this scan result was received using one or both the chains. 434 * {@hide} 435 */ 436 public RadioChainInfo[] radioChainInfos; 437 438 /** 439 * Status indicating the scan result does not correspond to a user's saved configuration 440 * @hide 441 * @removed 442 */ 443 @SystemApi 444 public boolean untrusted; 445 446 /** 447 * Number of time autojoin used it 448 * @hide 449 */ 450 @UnsupportedAppUsage 451 public int numUsage; 452 453 /** 454 * The approximate distance to the AP in centimeter, if available. Else 455 * {@link UNSPECIFIED}. 456 * {@hide} 457 */ 458 @UnsupportedAppUsage 459 public int distanceCm; 460 461 /** 462 * The standard deviation of the distance to the access point, if available. 463 * Else {@link UNSPECIFIED}. 464 * {@hide} 465 */ 466 @UnsupportedAppUsage 467 public int distanceSdCm; 468 469 /** {@hide} */ 470 public static final long FLAG_PASSPOINT_NETWORK = 0x0000000000000001; 471 472 /** {@hide} */ 473 public static final long FLAG_80211mc_RESPONDER = 0x0000000000000002; 474 475 /* 476 * These flags are specific to the ScanResult class, and are not related to the |flags| 477 * field of the per-BSS scan results from WPA supplicant. 478 */ 479 /** 480 * Defines flags; such as {@link #FLAG_PASSPOINT_NETWORK}. 481 * {@hide} 482 */ 483 @UnsupportedAppUsage 484 public long flags; 485 486 /** 487 * sets a flag in {@link #flags} field 488 * @param flag flag to set 489 * @hide 490 */ setFlag(long flag)491 public void setFlag(long flag) { 492 flags |= flag; 493 } 494 495 /** 496 * clears a flag in {@link #flags} field 497 * @param flag flag to set 498 * @hide 499 */ clearFlag(long flag)500 public void clearFlag(long flag) { 501 flags &= ~flag; 502 } 503 is80211mcResponder()504 public boolean is80211mcResponder() { 505 return (flags & FLAG_80211mc_RESPONDER) != 0; 506 } 507 isPasspointNetwork()508 public boolean isPasspointNetwork() { 509 return (flags & FLAG_PASSPOINT_NETWORK) != 0; 510 } 511 512 /** 513 * Indicates venue name (such as 'San Francisco Airport') published by access point; only 514 * available on Passpoint network and if published by access point. 515 */ 516 public CharSequence venueName; 517 518 /** 519 * Indicates Passpoint operator name published by access point. 520 */ 521 public CharSequence operatorFriendlyName; 522 523 /** 524 * {@hide} 525 */ 526 public final static int UNSPECIFIED = -1; 527 528 /** 529 * 2.4 GHz band first channel number 530 * @hide 531 */ 532 public static final int BAND_24_GHZ_FIRST_CH_NUM = 1; 533 /** 534 * 2.4 GHz band last channel number 535 * @hide 536 */ 537 public static final int BAND_24_GHZ_LAST_CH_NUM = 14; 538 /** 539 * 2.4 GHz band frequency of first channel in MHz 540 * @hide 541 */ 542 public static final int BAND_24_GHZ_START_FREQ_MHZ = 2412; 543 /** 544 * 2.4 GHz band frequency of last channel in MHz 545 * @hide 546 */ 547 public static final int BAND_24_GHZ_END_FREQ_MHZ = 2484; 548 549 /** 550 * 5 GHz band first channel number 551 * @hide 552 */ 553 public static final int BAND_5_GHZ_FIRST_CH_NUM = 32; 554 /** 555 * 5 GHz band last channel number 556 * @hide 557 */ 558 public static final int BAND_5_GHZ_LAST_CH_NUM = 173; 559 /** 560 * 5 GHz band frequency of first channel in MHz 561 * @hide 562 */ 563 public static final int BAND_5_GHZ_START_FREQ_MHZ = 5160; 564 /** 565 * 5 GHz band frequency of last channel in MHz 566 * @hide 567 */ 568 public static final int BAND_5_GHZ_END_FREQ_MHZ = 5865; 569 570 /** 571 * 6 GHz band first channel number 572 * @hide 573 */ 574 public static final int BAND_6_GHZ_FIRST_CH_NUM = 1; 575 /** 576 * 6 GHz band last channel number 577 * @hide 578 */ 579 public static final int BAND_6_GHZ_LAST_CH_NUM = 233; 580 /** 581 * 6 GHz band frequency of first channel in MHz 582 * @hide 583 */ 584 public static final int BAND_6_GHZ_START_FREQ_MHZ = 5945; 585 /** 586 * 6 GHz band frequency of last channel in MHz 587 * @hide 588 */ 589 public static final int BAND_6_GHZ_END_FREQ_MHZ = 7105; 590 591 /** 592 * Utility function to check if a frequency within 2.4 GHz band 593 * @param freqMhz frequency in MHz 594 * @return true if within 2.4GHz, false otherwise 595 * 596 * @hide 597 */ is24GHz(int freqMhz)598 public static boolean is24GHz(int freqMhz) { 599 return freqMhz >= BAND_24_GHZ_START_FREQ_MHZ && freqMhz <= BAND_24_GHZ_END_FREQ_MHZ; 600 } 601 602 /** 603 * Utility function to check if a frequency within 5 GHz band 604 * @param freqMhz frequency in MHz 605 * @return true if within 5GHz, false otherwise 606 * 607 * @hide 608 */ is5GHz(int freqMhz)609 public static boolean is5GHz(int freqMhz) { 610 return freqMhz >= BAND_5_GHZ_START_FREQ_MHZ && freqMhz <= BAND_5_GHZ_END_FREQ_MHZ; 611 } 612 613 /** 614 * Utility function to check if a frequency within 6 GHz band 615 * @param freqMhz 616 * @return true if within 6GHz, false otherwise 617 * 618 * @hide 619 */ is6GHz(int freqMhz)620 public static boolean is6GHz(int freqMhz) { 621 return freqMhz >= BAND_6_GHZ_START_FREQ_MHZ && freqMhz <= BAND_6_GHZ_END_FREQ_MHZ; 622 } 623 624 /** 625 * Utility function to convert channel number/band to frequency in MHz 626 * @param channel number to convert 627 * @param band of channel to convert 628 * @return center frequency in Mhz of the channel, {@link UNSPECIFIED} if no match 629 * 630 * @hide 631 */ convertChannelToFrequencyMhz(int channel, @WifiScanner.WifiBand int band)632 public static int convertChannelToFrequencyMhz(int channel, @WifiScanner.WifiBand int band) { 633 if (band == WifiScanner.WIFI_BAND_24_GHZ) { 634 // Special case 635 if (channel == 14) { 636 return 2484; 637 } else if (channel >= BAND_24_GHZ_FIRST_CH_NUM && channel <= BAND_24_GHZ_LAST_CH_NUM) { 638 return ((channel - BAND_24_GHZ_FIRST_CH_NUM) * 5) + BAND_24_GHZ_START_FREQ_MHZ; 639 } else { 640 return UNSPECIFIED; 641 } 642 } 643 if (band == WifiScanner.WIFI_BAND_5_GHZ) { 644 if (channel >= BAND_5_GHZ_FIRST_CH_NUM && channel <= BAND_5_GHZ_LAST_CH_NUM) { 645 return ((channel - BAND_5_GHZ_FIRST_CH_NUM) * 5) + BAND_5_GHZ_START_FREQ_MHZ; 646 } else { 647 return UNSPECIFIED; 648 } 649 } 650 if (band == WifiScanner.WIFI_BAND_6_GHZ) { 651 if (channel >= BAND_6_GHZ_FIRST_CH_NUM && channel <= BAND_6_GHZ_LAST_CH_NUM) { 652 return ((channel - BAND_6_GHZ_FIRST_CH_NUM) * 5) + BAND_6_GHZ_START_FREQ_MHZ; 653 } else { 654 return UNSPECIFIED; 655 } 656 } 657 return UNSPECIFIED; 658 } 659 660 /** 661 * Utility function to convert frequency in MHz to channel number 662 * @param freqMhz frequency in MHz 663 * @return channel number associated with given frequency, {@link UNSPECIFIED} if no match 664 * 665 * @hide 666 */ convertFrequencyMhzToChannel(int freqMhz)667 public static int convertFrequencyMhzToChannel(int freqMhz) { 668 // Special case 669 if (freqMhz == 2484) { 670 return 14; 671 } else if (is24GHz(freqMhz)) { 672 return (freqMhz - BAND_24_GHZ_START_FREQ_MHZ) / 5 + BAND_24_GHZ_FIRST_CH_NUM; 673 } else if (is5GHz(freqMhz)) { 674 return ((freqMhz - BAND_5_GHZ_START_FREQ_MHZ) / 5) + BAND_5_GHZ_FIRST_CH_NUM; 675 } else if (is6GHz(freqMhz)) { 676 return ((freqMhz - BAND_6_GHZ_START_FREQ_MHZ) / 5) + BAND_6_GHZ_FIRST_CH_NUM; 677 } 678 679 return UNSPECIFIED; 680 } 681 682 /** 683 * @hide 684 */ is24GHz()685 public boolean is24GHz() { 686 return ScanResult.is24GHz(frequency); 687 } 688 689 /** 690 * @hide 691 */ is5GHz()692 public boolean is5GHz() { 693 return ScanResult.is5GHz(frequency); 694 } 695 696 /** 697 * @hide 698 */ is6GHz()699 public boolean is6GHz() { 700 return ScanResult.is6GHz(frequency); 701 } 702 703 /** 704 * @hide 705 * anqp lines from supplicant BSS response 706 */ 707 @UnsupportedAppUsage 708 public List<String> anqpLines; 709 710 /** 711 * information elements from beacon. 712 */ 713 public static class InformationElement { 714 /** @hide */ 715 @UnsupportedAppUsage 716 public static final int EID_SSID = 0; 717 /** @hide */ 718 @UnsupportedAppUsage 719 public static final int EID_SUPPORTED_RATES = 1; 720 /** @hide */ 721 @UnsupportedAppUsage 722 public static final int EID_TIM = 5; 723 /** @hide */ 724 @UnsupportedAppUsage 725 public static final int EID_BSS_LOAD = 11; 726 /** @hide */ 727 @UnsupportedAppUsage 728 public static final int EID_ERP = 42; 729 /** @hide */ 730 public static final int EID_HT_CAPABILITIES = 45; 731 /** @hide */ 732 @UnsupportedAppUsage 733 public static final int EID_RSN = 48; 734 /** @hide */ 735 @UnsupportedAppUsage 736 public static final int EID_EXTENDED_SUPPORTED_RATES = 50; 737 /** @hide */ 738 @UnsupportedAppUsage 739 public static final int EID_HT_OPERATION = 61; 740 /** @hide */ 741 @UnsupportedAppUsage 742 public static final int EID_INTERWORKING = 107; 743 /** @hide */ 744 @UnsupportedAppUsage 745 public static final int EID_ROAMING_CONSORTIUM = 111; 746 /** @hide */ 747 @UnsupportedAppUsage 748 public static final int EID_EXTENDED_CAPS = 127; 749 /** @hide */ 750 public static final int EID_VHT_CAPABILITIES = 191; 751 /** @hide */ 752 @UnsupportedAppUsage 753 public static final int EID_VHT_OPERATION = 192; 754 /** @hide */ 755 @UnsupportedAppUsage 756 public static final int EID_VSA = 221; 757 /** @hide */ 758 public static final int EID_EXTENSION_PRESENT = 255; 759 760 // Extension IDs 761 /** @hide */ 762 public static final int EID_EXT_HE_CAPABILITIES = 35; 763 /** @hide */ 764 public static final int EID_EXT_HE_OPERATION = 36; 765 766 /** @hide */ 767 @UnsupportedAppUsage 768 public int id; 769 /** @hide */ 770 public int idExt; 771 772 /** @hide */ 773 @UnsupportedAppUsage 774 public byte[] bytes; 775 776 /** @hide */ InformationElement()777 public InformationElement() { 778 } 779 InformationElement(@onNull InformationElement rhs)780 public InformationElement(@NonNull InformationElement rhs) { 781 this.id = rhs.id; 782 this.idExt = rhs.idExt; 783 this.bytes = rhs.bytes.clone(); 784 } 785 786 /** 787 * The element ID of the information element. Defined in the IEEE 802.11-2016 spec 788 * Table 9-77. 789 */ getId()790 public int getId() { 791 return id; 792 } 793 794 /** 795 * The element ID Extension of the information element. Defined in the IEEE 802.11-2016 spec 796 * Table 9-77. 797 */ getIdExt()798 public int getIdExt() { 799 return idExt; 800 } 801 802 /** 803 * Get the specific content of the information element. 804 */ 805 @NonNull getBytes()806 public ByteBuffer getBytes() { 807 return ByteBuffer.wrap(bytes).asReadOnlyBuffer(); 808 } 809 } 810 811 /** 812 * information elements found in the beacon. 813 * @hide 814 */ 815 @UnsupportedAppUsage 816 public InformationElement[] informationElements; 817 /** 818 * Get all information elements found in the beacon. 819 */ 820 @NonNull getInformationElements()821 public List<InformationElement> getInformationElements() { 822 return Collections.unmodifiableList(Arrays.asList(informationElements)); 823 } 824 825 /** ANQP response elements. 826 * @hide 827 */ 828 public AnqpInformationElement[] anqpElements; 829 830 /** {@hide} */ ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId, byte[] osuProviders, String caps, int level, int frequency, long tsf)831 public ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId, 832 byte[] osuProviders, String caps, int level, int frequency, long tsf) { 833 this.wifiSsid = wifiSsid; 834 this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiManager.UNKNOWN_SSID; 835 this.BSSID = BSSID; 836 this.hessid = hessid; 837 this.anqpDomainId = anqpDomainId; 838 if (osuProviders != null) { 839 this.anqpElements = new AnqpInformationElement[1]; 840 this.anqpElements[0] = 841 new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID, 842 AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders); 843 } 844 this.capabilities = caps; 845 this.level = level; 846 this.frequency = frequency; 847 this.timestamp = tsf; 848 this.distanceCm = UNSPECIFIED; 849 this.distanceSdCm = UNSPECIFIED; 850 this.channelWidth = UNSPECIFIED; 851 this.centerFreq0 = UNSPECIFIED; 852 this.centerFreq1 = UNSPECIFIED; 853 this.flags = 0; 854 this.radioChainInfos = null; 855 this.mWifiStandard = WIFI_STANDARD_UNKNOWN; 856 } 857 858 /** {@hide} */ ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency, long tsf, int distCm, int distSdCm)859 public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency, 860 long tsf, int distCm, int distSdCm) { 861 this.wifiSsid = wifiSsid; 862 this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiManager.UNKNOWN_SSID; 863 this.BSSID = BSSID; 864 this.capabilities = caps; 865 this.level = level; 866 this.frequency = frequency; 867 this.timestamp = tsf; 868 this.distanceCm = distCm; 869 this.distanceSdCm = distSdCm; 870 this.channelWidth = UNSPECIFIED; 871 this.centerFreq0 = UNSPECIFIED; 872 this.centerFreq1 = UNSPECIFIED; 873 this.flags = 0; 874 this.radioChainInfos = null; 875 this.mWifiStandard = WIFI_STANDARD_UNKNOWN; 876 } 877 878 /** {@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)879 public ScanResult(String Ssid, String BSSID, long hessid, int anqpDomainId, String caps, 880 int level, int frequency, 881 long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1, 882 boolean is80211McRTTResponder) { 883 this.SSID = Ssid; 884 this.BSSID = BSSID; 885 this.hessid = hessid; 886 this.anqpDomainId = anqpDomainId; 887 this.capabilities = caps; 888 this.level = level; 889 this.frequency = frequency; 890 this.timestamp = tsf; 891 this.distanceCm = distCm; 892 this.distanceSdCm = distSdCm; 893 this.channelWidth = channelWidth; 894 this.centerFreq0 = centerFreq0; 895 this.centerFreq1 = centerFreq1; 896 if (is80211McRTTResponder) { 897 this.flags = FLAG_80211mc_RESPONDER; 898 } else { 899 this.flags = 0; 900 } 901 this.radioChainInfos = null; 902 this.mWifiStandard = WIFI_STANDARD_UNKNOWN; 903 } 904 905 /** {@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)906 public ScanResult(WifiSsid wifiSsid, String Ssid, String BSSID, long hessid, int anqpDomainId, 907 String caps, int level, 908 int frequency, long tsf, int distCm, int distSdCm, int channelWidth, 909 int centerFreq0, int centerFreq1, boolean is80211McRTTResponder) { 910 this(Ssid, BSSID, hessid, anqpDomainId, caps, level, frequency, tsf, distCm, 911 distSdCm, channelWidth, centerFreq0, centerFreq1, is80211McRTTResponder); 912 this.wifiSsid = wifiSsid; 913 } 914 915 /** copy constructor */ ScanResult(@onNull ScanResult source)916 public ScanResult(@NonNull ScanResult source) { 917 if (source != null) { 918 wifiSsid = source.wifiSsid; 919 SSID = source.SSID; 920 BSSID = source.BSSID; 921 hessid = source.hessid; 922 anqpDomainId = source.anqpDomainId; 923 informationElements = source.informationElements; 924 anqpElements = source.anqpElements; 925 capabilities = source.capabilities; 926 level = source.level; 927 frequency = source.frequency; 928 channelWidth = source.channelWidth; 929 centerFreq0 = source.centerFreq0; 930 centerFreq1 = source.centerFreq1; 931 timestamp = source.timestamp; 932 distanceCm = source.distanceCm; 933 distanceSdCm = source.distanceSdCm; 934 seen = source.seen; 935 untrusted = source.untrusted; 936 numUsage = source.numUsage; 937 venueName = source.venueName; 938 operatorFriendlyName = source.operatorFriendlyName; 939 flags = source.flags; 940 radioChainInfos = source.radioChainInfos; 941 this.mWifiStandard = source.mWifiStandard; 942 } 943 } 944 945 /** Construct an empty scan result. */ ScanResult()946 public ScanResult() { 947 } 948 949 @Override toString()950 public String toString() { 951 StringBuffer sb = new StringBuffer(); 952 String none = "<none>"; 953 954 sb.append("SSID: ") 955 .append(wifiSsid == null ? WifiManager.UNKNOWN_SSID : wifiSsid) 956 .append(", BSSID: ") 957 .append(BSSID == null ? none : BSSID) 958 .append(", capabilities: ") 959 .append(capabilities == null ? none : capabilities) 960 .append(", level: ") 961 .append(level) 962 .append(", frequency: ") 963 .append(frequency) 964 .append(", timestamp: ") 965 .append(timestamp); 966 sb.append(", distance: ").append((distanceCm != UNSPECIFIED ? distanceCm : "?")). 967 append("(cm)"); 968 sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")). 969 append("(cm)"); 970 971 sb.append(", passpoint: "); 972 sb.append(((flags & FLAG_PASSPOINT_NETWORK) != 0) ? "yes" : "no"); 973 sb.append(", ChannelBandwidth: ").append(channelWidth); 974 sb.append(", centerFreq0: ").append(centerFreq0); 975 sb.append(", centerFreq1: ").append(centerFreq1); 976 sb.append(", standard: ").append(wifiStandardToString(mWifiStandard)); 977 sb.append(", 80211mcResponder: "); 978 sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported"); 979 sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos)); 980 return sb.toString(); 981 } 982 983 /** Implement the Parcelable interface {@hide} */ describeContents()984 public int describeContents() { 985 return 0; 986 } 987 988 /** Implement the Parcelable interface {@hide} */ writeToParcel(Parcel dest, int flags)989 public void writeToParcel(Parcel dest, int flags) { 990 if (wifiSsid != null) { 991 dest.writeInt(1); 992 wifiSsid.writeToParcel(dest, flags); 993 } else { 994 dest.writeInt(0); 995 } 996 dest.writeString(SSID); 997 dest.writeString(BSSID); 998 dest.writeLong(hessid); 999 dest.writeInt(anqpDomainId); 1000 dest.writeString(capabilities); 1001 dest.writeInt(level); 1002 dest.writeInt(frequency); 1003 dest.writeLong(timestamp); 1004 dest.writeInt(distanceCm); 1005 dest.writeInt(distanceSdCm); 1006 dest.writeInt(channelWidth); 1007 dest.writeInt(centerFreq0); 1008 dest.writeInt(centerFreq1); 1009 dest.writeInt(mWifiStandard); 1010 dest.writeLong(seen); 1011 dest.writeInt(untrusted ? 1 : 0); 1012 dest.writeInt(numUsage); 1013 dest.writeString((venueName != null) ? venueName.toString() : ""); 1014 dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : ""); 1015 dest.writeLong(this.flags); 1016 1017 if (informationElements != null) { 1018 dest.writeInt(informationElements.length); 1019 for (int i = 0; i < informationElements.length; i++) { 1020 dest.writeInt(informationElements[i].id); 1021 dest.writeInt(informationElements[i].idExt); 1022 dest.writeInt(informationElements[i].bytes.length); 1023 dest.writeByteArray(informationElements[i].bytes); 1024 } 1025 } else { 1026 dest.writeInt(0); 1027 } 1028 1029 if (anqpLines != null) { 1030 dest.writeInt(anqpLines.size()); 1031 for (int i = 0; i < anqpLines.size(); i++) { 1032 dest.writeString(anqpLines.get(i)); 1033 } 1034 } 1035 else { 1036 dest.writeInt(0); 1037 } 1038 if (anqpElements != null) { 1039 dest.writeInt(anqpElements.length); 1040 for (AnqpInformationElement element : anqpElements) { 1041 dest.writeInt(element.getVendorId()); 1042 dest.writeInt(element.getElementId()); 1043 dest.writeInt(element.getPayload().length); 1044 dest.writeByteArray(element.getPayload()); 1045 } 1046 } else { 1047 dest.writeInt(0); 1048 } 1049 1050 if (radioChainInfos != null) { 1051 dest.writeInt(radioChainInfos.length); 1052 for (int i = 0; i < radioChainInfos.length; i++) { 1053 dest.writeInt(radioChainInfos[i].id); 1054 dest.writeInt(radioChainInfos[i].level); 1055 } 1056 } else { 1057 dest.writeInt(0); 1058 } 1059 } 1060 1061 /** Implement the Parcelable interface */ 1062 public static final @NonNull Creator<ScanResult> CREATOR = 1063 new Creator<ScanResult>() { 1064 public ScanResult createFromParcel(Parcel in) { 1065 WifiSsid wifiSsid = null; 1066 if (in.readInt() == 1) { 1067 wifiSsid = WifiSsid.CREATOR.createFromParcel(in); 1068 } 1069 ScanResult sr = new ScanResult( 1070 wifiSsid, 1071 in.readString(), /* SSID */ 1072 in.readString(), /* BSSID */ 1073 in.readLong(), /* HESSID */ 1074 in.readInt(), /* ANQP Domain ID */ 1075 in.readString(), /* capabilities */ 1076 in.readInt(), /* level */ 1077 in.readInt(), /* frequency */ 1078 in.readLong(), /* timestamp */ 1079 in.readInt(), /* distanceCm */ 1080 in.readInt(), /* distanceSdCm */ 1081 in.readInt(), /* channelWidth */ 1082 in.readInt(), /* centerFreq0 */ 1083 in.readInt(), /* centerFreq1 */ 1084 false /* rtt responder, 1085 fixed with flags below */ 1086 ); 1087 1088 sr.mWifiStandard = in.readInt(); 1089 sr.seen = in.readLong(); 1090 sr.untrusted = in.readInt() != 0; 1091 sr.numUsage = in.readInt(); 1092 sr.venueName = in.readString(); 1093 sr.operatorFriendlyName = in.readString(); 1094 sr.flags = in.readLong(); 1095 int n = in.readInt(); 1096 if (n != 0) { 1097 sr.informationElements = new InformationElement[n]; 1098 for (int i = 0; i < n; i++) { 1099 sr.informationElements[i] = new InformationElement(); 1100 sr.informationElements[i].id = in.readInt(); 1101 sr.informationElements[i].idExt = in.readInt(); 1102 int len = in.readInt(); 1103 sr.informationElements[i].bytes = new byte[len]; 1104 in.readByteArray(sr.informationElements[i].bytes); 1105 } 1106 } 1107 1108 n = in.readInt(); 1109 if (n != 0) { 1110 sr.anqpLines = new ArrayList<String>(); 1111 for (int i = 0; i < n; i++) { 1112 sr.anqpLines.add(in.readString()); 1113 } 1114 } 1115 n = in.readInt(); 1116 if (n != 0) { 1117 sr.anqpElements = new AnqpInformationElement[n]; 1118 for (int i = 0; i < n; i++) { 1119 int vendorId = in.readInt(); 1120 int elementId = in.readInt(); 1121 int len = in.readInt(); 1122 byte[] payload = new byte[len]; 1123 in.readByteArray(payload); 1124 sr.anqpElements[i] = 1125 new AnqpInformationElement(vendorId, elementId, payload); 1126 } 1127 } 1128 n = in.readInt(); 1129 if (n != 0) { 1130 sr.radioChainInfos = new RadioChainInfo[n]; 1131 for (int i = 0; i < n; i++) { 1132 sr.radioChainInfos[i] = new RadioChainInfo(); 1133 sr.radioChainInfos[i].id = in.readInt(); 1134 sr.radioChainInfos[i].level = in.readInt(); 1135 } 1136 } 1137 return sr; 1138 } 1139 1140 public ScanResult[] newArray(int size) { 1141 return new ScanResult[size]; 1142 } 1143 }; 1144 } 1145