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 = 5955; 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 = 7115; 590 591 /** 592 * 6 GHz band operating class 136 channel 2 center frequency in MHz 593 * @hide 594 */ 595 public static final int BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ = 5935; 596 597 /** 598 * Utility function to check if a frequency within 2.4 GHz band 599 * @param freqMhz frequency in MHz 600 * @return true if within 2.4GHz, false otherwise 601 * 602 * @hide 603 */ is24GHz(int freqMhz)604 public static boolean is24GHz(int freqMhz) { 605 return freqMhz >= BAND_24_GHZ_START_FREQ_MHZ && freqMhz <= BAND_24_GHZ_END_FREQ_MHZ; 606 } 607 608 /** 609 * Utility function to check if a frequency within 5 GHz band 610 * @param freqMhz frequency in MHz 611 * @return true if within 5GHz, false otherwise 612 * 613 * @hide 614 */ is5GHz(int freqMhz)615 public static boolean is5GHz(int freqMhz) { 616 return freqMhz >= BAND_5_GHZ_START_FREQ_MHZ && freqMhz <= BAND_5_GHZ_END_FREQ_MHZ; 617 } 618 619 /** 620 * Utility function to check if a frequency within 6 GHz band 621 * @param freqMhz 622 * @return true if within 6GHz, false otherwise 623 * 624 * @hide 625 */ is6GHz(int freqMhz)626 public static boolean is6GHz(int freqMhz) { 627 if (freqMhz == BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ) { 628 return true; 629 } 630 return (freqMhz >= BAND_6_GHZ_START_FREQ_MHZ && freqMhz <= BAND_6_GHZ_END_FREQ_MHZ); 631 } 632 633 /** 634 * Utility function to convert channel number/band to frequency in MHz 635 * @param channel number to convert 636 * @param band of channel to convert 637 * @return center frequency in Mhz of the channel, {@link UNSPECIFIED} if no match 638 * 639 * @hide 640 */ convertChannelToFrequencyMhz(int channel, @WifiScanner.WifiBand int band)641 public static int convertChannelToFrequencyMhz(int channel, @WifiScanner.WifiBand int band) { 642 if (band == WifiScanner.WIFI_BAND_24_GHZ) { 643 // Special case 644 if (channel == 14) { 645 return 2484; 646 } else if (channel >= BAND_24_GHZ_FIRST_CH_NUM && channel <= BAND_24_GHZ_LAST_CH_NUM) { 647 return ((channel - BAND_24_GHZ_FIRST_CH_NUM) * 5) + BAND_24_GHZ_START_FREQ_MHZ; 648 } else { 649 return UNSPECIFIED; 650 } 651 } 652 if (band == WifiScanner.WIFI_BAND_5_GHZ) { 653 if (channel >= BAND_5_GHZ_FIRST_CH_NUM && channel <= BAND_5_GHZ_LAST_CH_NUM) { 654 return ((channel - BAND_5_GHZ_FIRST_CH_NUM) * 5) + BAND_5_GHZ_START_FREQ_MHZ; 655 } else { 656 return UNSPECIFIED; 657 } 658 } 659 if (band == WifiScanner.WIFI_BAND_6_GHZ) { 660 if (channel >= BAND_6_GHZ_FIRST_CH_NUM && channel <= BAND_6_GHZ_LAST_CH_NUM) { 661 if (channel == 2) { 662 return BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ; 663 } 664 return ((channel - BAND_6_GHZ_FIRST_CH_NUM) * 5) + BAND_6_GHZ_START_FREQ_MHZ; 665 } else { 666 return UNSPECIFIED; 667 } 668 } 669 return UNSPECIFIED; 670 } 671 672 /** 673 * Utility function to convert frequency in MHz to channel number 674 * @param freqMhz frequency in MHz 675 * @return channel number associated with given frequency, {@link UNSPECIFIED} if no match 676 * 677 * @hide 678 */ convertFrequencyMhzToChannel(int freqMhz)679 public static int convertFrequencyMhzToChannel(int freqMhz) { 680 // Special case 681 if (freqMhz == 2484) { 682 return 14; 683 } else if (is24GHz(freqMhz)) { 684 return (freqMhz - BAND_24_GHZ_START_FREQ_MHZ) / 5 + BAND_24_GHZ_FIRST_CH_NUM; 685 } else if (is5GHz(freqMhz)) { 686 return ((freqMhz - BAND_5_GHZ_START_FREQ_MHZ) / 5) + BAND_5_GHZ_FIRST_CH_NUM; 687 } else if (is6GHz(freqMhz)) { 688 if (freqMhz == BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ) { 689 return 2; 690 } 691 return ((freqMhz - BAND_6_GHZ_START_FREQ_MHZ) / 5) + BAND_6_GHZ_FIRST_CH_NUM; 692 } 693 694 return UNSPECIFIED; 695 } 696 697 /** 698 * @hide 699 */ is24GHz()700 public boolean is24GHz() { 701 return ScanResult.is24GHz(frequency); 702 } 703 704 /** 705 * @hide 706 */ is5GHz()707 public boolean is5GHz() { 708 return ScanResult.is5GHz(frequency); 709 } 710 711 /** 712 * @hide 713 */ is6GHz()714 public boolean is6GHz() { 715 return ScanResult.is6GHz(frequency); 716 } 717 718 /** 719 * @hide 720 * anqp lines from supplicant BSS response 721 */ 722 @UnsupportedAppUsage 723 public List<String> anqpLines; 724 725 /** 726 * information elements from beacon. 727 */ 728 public static class InformationElement { 729 /** @hide */ 730 @UnsupportedAppUsage 731 public static final int EID_SSID = 0; 732 /** @hide */ 733 @UnsupportedAppUsage 734 public static final int EID_SUPPORTED_RATES = 1; 735 /** @hide */ 736 @UnsupportedAppUsage 737 public static final int EID_TIM = 5; 738 /** @hide */ 739 @UnsupportedAppUsage 740 public static final int EID_BSS_LOAD = 11; 741 /** @hide */ 742 @UnsupportedAppUsage 743 public static final int EID_ERP = 42; 744 /** @hide */ 745 public static final int EID_HT_CAPABILITIES = 45; 746 /** @hide */ 747 @UnsupportedAppUsage 748 public static final int EID_RSN = 48; 749 /** @hide */ 750 @UnsupportedAppUsage 751 public static final int EID_EXTENDED_SUPPORTED_RATES = 50; 752 /** @hide */ 753 @UnsupportedAppUsage 754 public static final int EID_HT_OPERATION = 61; 755 /** @hide */ 756 @UnsupportedAppUsage 757 public static final int EID_INTERWORKING = 107; 758 /** @hide */ 759 @UnsupportedAppUsage 760 public static final int EID_ROAMING_CONSORTIUM = 111; 761 /** @hide */ 762 @UnsupportedAppUsage 763 public static final int EID_EXTENDED_CAPS = 127; 764 /** @hide */ 765 public static final int EID_VHT_CAPABILITIES = 191; 766 /** @hide */ 767 @UnsupportedAppUsage 768 public static final int EID_VHT_OPERATION = 192; 769 /** @hide */ 770 @UnsupportedAppUsage 771 public static final int EID_VSA = 221; 772 /** @hide */ 773 public static final int EID_EXTENSION_PRESENT = 255; 774 775 // Extension IDs 776 /** @hide */ 777 public static final int EID_EXT_HE_CAPABILITIES = 35; 778 /** @hide */ 779 public static final int EID_EXT_HE_OPERATION = 36; 780 781 /** @hide */ 782 @UnsupportedAppUsage 783 public int id; 784 /** @hide */ 785 public int idExt; 786 787 /** @hide */ 788 @UnsupportedAppUsage 789 public byte[] bytes; 790 791 /** @hide */ InformationElement()792 public InformationElement() { 793 } 794 InformationElement(@onNull InformationElement rhs)795 public InformationElement(@NonNull InformationElement rhs) { 796 this.id = rhs.id; 797 this.idExt = rhs.idExt; 798 this.bytes = rhs.bytes.clone(); 799 } 800 801 /** 802 * The element ID of the information element. Defined in the IEEE 802.11-2016 spec 803 * Table 9-77. 804 */ getId()805 public int getId() { 806 return id; 807 } 808 809 /** 810 * The element ID Extension of the information element. Defined in the IEEE 802.11-2016 spec 811 * Table 9-77. 812 */ getIdExt()813 public int getIdExt() { 814 return idExt; 815 } 816 817 /** 818 * Get the specific content of the information element. 819 */ 820 @NonNull getBytes()821 public ByteBuffer getBytes() { 822 return ByteBuffer.wrap(bytes).asReadOnlyBuffer(); 823 } 824 } 825 826 /** 827 * information elements found in the beacon. 828 * @hide 829 */ 830 @UnsupportedAppUsage 831 public InformationElement[] informationElements; 832 /** 833 * Get all information elements found in the beacon. 834 */ 835 @NonNull getInformationElements()836 public List<InformationElement> getInformationElements() { 837 return Collections.unmodifiableList(Arrays.asList(informationElements)); 838 } 839 840 /** ANQP response elements. 841 * @hide 842 */ 843 public AnqpInformationElement[] anqpElements; 844 845 /** {@hide} */ ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId, byte[] osuProviders, String caps, int level, int frequency, long tsf)846 public ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId, 847 byte[] osuProviders, String caps, int level, int frequency, long tsf) { 848 this.wifiSsid = wifiSsid; 849 this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiManager.UNKNOWN_SSID; 850 this.BSSID = BSSID; 851 this.hessid = hessid; 852 this.anqpDomainId = anqpDomainId; 853 if (osuProviders != null) { 854 this.anqpElements = new AnqpInformationElement[1]; 855 this.anqpElements[0] = 856 new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID, 857 AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders); 858 } 859 this.capabilities = caps; 860 this.level = level; 861 this.frequency = frequency; 862 this.timestamp = tsf; 863 this.distanceCm = UNSPECIFIED; 864 this.distanceSdCm = UNSPECIFIED; 865 this.channelWidth = UNSPECIFIED; 866 this.centerFreq0 = UNSPECIFIED; 867 this.centerFreq1 = UNSPECIFIED; 868 this.flags = 0; 869 this.radioChainInfos = null; 870 this.mWifiStandard = WIFI_STANDARD_UNKNOWN; 871 } 872 873 /** {@hide} */ ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency, long tsf, int distCm, int distSdCm)874 public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency, 875 long tsf, int distCm, int distSdCm) { 876 this.wifiSsid = wifiSsid; 877 this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiManager.UNKNOWN_SSID; 878 this.BSSID = BSSID; 879 this.capabilities = caps; 880 this.level = level; 881 this.frequency = frequency; 882 this.timestamp = tsf; 883 this.distanceCm = distCm; 884 this.distanceSdCm = distSdCm; 885 this.channelWidth = UNSPECIFIED; 886 this.centerFreq0 = UNSPECIFIED; 887 this.centerFreq1 = UNSPECIFIED; 888 this.flags = 0; 889 this.radioChainInfos = null; 890 this.mWifiStandard = WIFI_STANDARD_UNKNOWN; 891 } 892 893 /** {@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)894 public ScanResult(String Ssid, String BSSID, long hessid, int anqpDomainId, String caps, 895 int level, int frequency, 896 long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1, 897 boolean is80211McRTTResponder) { 898 this.SSID = Ssid; 899 this.BSSID = BSSID; 900 this.hessid = hessid; 901 this.anqpDomainId = anqpDomainId; 902 this.capabilities = caps; 903 this.level = level; 904 this.frequency = frequency; 905 this.timestamp = tsf; 906 this.distanceCm = distCm; 907 this.distanceSdCm = distSdCm; 908 this.channelWidth = channelWidth; 909 this.centerFreq0 = centerFreq0; 910 this.centerFreq1 = centerFreq1; 911 if (is80211McRTTResponder) { 912 this.flags = FLAG_80211mc_RESPONDER; 913 } else { 914 this.flags = 0; 915 } 916 this.radioChainInfos = null; 917 this.mWifiStandard = WIFI_STANDARD_UNKNOWN; 918 } 919 920 /** {@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)921 public ScanResult(WifiSsid wifiSsid, String Ssid, String BSSID, long hessid, int anqpDomainId, 922 String caps, int level, 923 int frequency, long tsf, int distCm, int distSdCm, int channelWidth, 924 int centerFreq0, int centerFreq1, boolean is80211McRTTResponder) { 925 this(Ssid, BSSID, hessid, anqpDomainId, caps, level, frequency, tsf, distCm, 926 distSdCm, channelWidth, centerFreq0, centerFreq1, is80211McRTTResponder); 927 this.wifiSsid = wifiSsid; 928 } 929 930 /** copy constructor */ ScanResult(@onNull ScanResult source)931 public ScanResult(@NonNull ScanResult source) { 932 if (source != null) { 933 wifiSsid = source.wifiSsid; 934 SSID = source.SSID; 935 BSSID = source.BSSID; 936 hessid = source.hessid; 937 anqpDomainId = source.anqpDomainId; 938 informationElements = source.informationElements; 939 anqpElements = source.anqpElements; 940 capabilities = source.capabilities; 941 level = source.level; 942 frequency = source.frequency; 943 channelWidth = source.channelWidth; 944 centerFreq0 = source.centerFreq0; 945 centerFreq1 = source.centerFreq1; 946 timestamp = source.timestamp; 947 distanceCm = source.distanceCm; 948 distanceSdCm = source.distanceSdCm; 949 seen = source.seen; 950 untrusted = source.untrusted; 951 numUsage = source.numUsage; 952 venueName = source.venueName; 953 operatorFriendlyName = source.operatorFriendlyName; 954 flags = source.flags; 955 radioChainInfos = source.radioChainInfos; 956 this.mWifiStandard = source.mWifiStandard; 957 } 958 } 959 960 /** Construct an empty scan result. */ ScanResult()961 public ScanResult() { 962 } 963 964 @Override toString()965 public String toString() { 966 StringBuffer sb = new StringBuffer(); 967 String none = "<none>"; 968 969 sb.append("SSID: ") 970 .append(wifiSsid == null ? WifiManager.UNKNOWN_SSID : wifiSsid) 971 .append(", BSSID: ") 972 .append(BSSID == null ? none : BSSID) 973 .append(", capabilities: ") 974 .append(capabilities == null ? none : capabilities) 975 .append(", level: ") 976 .append(level) 977 .append(", frequency: ") 978 .append(frequency) 979 .append(", timestamp: ") 980 .append(timestamp); 981 sb.append(", distance: ").append((distanceCm != UNSPECIFIED ? distanceCm : "?")). 982 append("(cm)"); 983 sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")). 984 append("(cm)"); 985 986 sb.append(", passpoint: "); 987 sb.append(((flags & FLAG_PASSPOINT_NETWORK) != 0) ? "yes" : "no"); 988 sb.append(", ChannelBandwidth: ").append(channelWidth); 989 sb.append(", centerFreq0: ").append(centerFreq0); 990 sb.append(", centerFreq1: ").append(centerFreq1); 991 sb.append(", standard: ").append(wifiStandardToString(mWifiStandard)); 992 sb.append(", 80211mcResponder: "); 993 sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported"); 994 sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos)); 995 return sb.toString(); 996 } 997 998 /** Implement the Parcelable interface {@hide} */ describeContents()999 public int describeContents() { 1000 return 0; 1001 } 1002 1003 /** Implement the Parcelable interface {@hide} */ writeToParcel(Parcel dest, int flags)1004 public void writeToParcel(Parcel dest, int flags) { 1005 if (wifiSsid != null) { 1006 dest.writeInt(1); 1007 wifiSsid.writeToParcel(dest, flags); 1008 } else { 1009 dest.writeInt(0); 1010 } 1011 dest.writeString(SSID); 1012 dest.writeString(BSSID); 1013 dest.writeLong(hessid); 1014 dest.writeInt(anqpDomainId); 1015 dest.writeString(capabilities); 1016 dest.writeInt(level); 1017 dest.writeInt(frequency); 1018 dest.writeLong(timestamp); 1019 dest.writeInt(distanceCm); 1020 dest.writeInt(distanceSdCm); 1021 dest.writeInt(channelWidth); 1022 dest.writeInt(centerFreq0); 1023 dest.writeInt(centerFreq1); 1024 dest.writeInt(mWifiStandard); 1025 dest.writeLong(seen); 1026 dest.writeInt(untrusted ? 1 : 0); 1027 dest.writeInt(numUsage); 1028 dest.writeString((venueName != null) ? venueName.toString() : ""); 1029 dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : ""); 1030 dest.writeLong(this.flags); 1031 1032 if (informationElements != null) { 1033 dest.writeInt(informationElements.length); 1034 for (int i = 0; i < informationElements.length; i++) { 1035 dest.writeInt(informationElements[i].id); 1036 dest.writeInt(informationElements[i].idExt); 1037 dest.writeInt(informationElements[i].bytes.length); 1038 dest.writeByteArray(informationElements[i].bytes); 1039 } 1040 } else { 1041 dest.writeInt(0); 1042 } 1043 1044 if (anqpLines != null) { 1045 dest.writeInt(anqpLines.size()); 1046 for (int i = 0; i < anqpLines.size(); i++) { 1047 dest.writeString(anqpLines.get(i)); 1048 } 1049 } 1050 else { 1051 dest.writeInt(0); 1052 } 1053 if (anqpElements != null) { 1054 dest.writeInt(anqpElements.length); 1055 for (AnqpInformationElement element : anqpElements) { 1056 dest.writeInt(element.getVendorId()); 1057 dest.writeInt(element.getElementId()); 1058 dest.writeInt(element.getPayload().length); 1059 dest.writeByteArray(element.getPayload()); 1060 } 1061 } else { 1062 dest.writeInt(0); 1063 } 1064 1065 if (radioChainInfos != null) { 1066 dest.writeInt(radioChainInfos.length); 1067 for (int i = 0; i < radioChainInfos.length; i++) { 1068 dest.writeInt(radioChainInfos[i].id); 1069 dest.writeInt(radioChainInfos[i].level); 1070 } 1071 } else { 1072 dest.writeInt(0); 1073 } 1074 } 1075 1076 /** Implement the Parcelable interface */ 1077 public static final @NonNull Creator<ScanResult> CREATOR = 1078 new Creator<ScanResult>() { 1079 public ScanResult createFromParcel(Parcel in) { 1080 WifiSsid wifiSsid = null; 1081 if (in.readInt() == 1) { 1082 wifiSsid = WifiSsid.CREATOR.createFromParcel(in); 1083 } 1084 ScanResult sr = new ScanResult( 1085 wifiSsid, 1086 in.readString(), /* SSID */ 1087 in.readString(), /* BSSID */ 1088 in.readLong(), /* HESSID */ 1089 in.readInt(), /* ANQP Domain ID */ 1090 in.readString(), /* capabilities */ 1091 in.readInt(), /* level */ 1092 in.readInt(), /* frequency */ 1093 in.readLong(), /* timestamp */ 1094 in.readInt(), /* distanceCm */ 1095 in.readInt(), /* distanceSdCm */ 1096 in.readInt(), /* channelWidth */ 1097 in.readInt(), /* centerFreq0 */ 1098 in.readInt(), /* centerFreq1 */ 1099 false /* rtt responder, 1100 fixed with flags below */ 1101 ); 1102 1103 sr.mWifiStandard = in.readInt(); 1104 sr.seen = in.readLong(); 1105 sr.untrusted = in.readInt() != 0; 1106 sr.numUsage = in.readInt(); 1107 sr.venueName = in.readString(); 1108 sr.operatorFriendlyName = in.readString(); 1109 sr.flags = in.readLong(); 1110 int n = in.readInt(); 1111 if (n != 0) { 1112 sr.informationElements = new InformationElement[n]; 1113 for (int i = 0; i < n; i++) { 1114 sr.informationElements[i] = new InformationElement(); 1115 sr.informationElements[i].id = in.readInt(); 1116 sr.informationElements[i].idExt = in.readInt(); 1117 int len = in.readInt(); 1118 sr.informationElements[i].bytes = new byte[len]; 1119 in.readByteArray(sr.informationElements[i].bytes); 1120 } 1121 } 1122 1123 n = in.readInt(); 1124 if (n != 0) { 1125 sr.anqpLines = new ArrayList<String>(); 1126 for (int i = 0; i < n; i++) { 1127 sr.anqpLines.add(in.readString()); 1128 } 1129 } 1130 n = in.readInt(); 1131 if (n != 0) { 1132 sr.anqpElements = new AnqpInformationElement[n]; 1133 for (int i = 0; i < n; i++) { 1134 int vendorId = in.readInt(); 1135 int elementId = in.readInt(); 1136 int len = in.readInt(); 1137 byte[] payload = new byte[len]; 1138 in.readByteArray(payload); 1139 sr.anqpElements[i] = 1140 new AnqpInformationElement(vendorId, elementId, payload); 1141 } 1142 } 1143 n = in.readInt(); 1144 if (n != 0) { 1145 sr.radioChainInfos = new RadioChainInfo[n]; 1146 for (int i = 0; i < n; i++) { 1147 sr.radioChainInfos[i] = new RadioChainInfo(); 1148 sr.radioChainInfos[i].id = in.readInt(); 1149 sr.radioChainInfos[i].level = in.readInt(); 1150 } 1151 } 1152 return sr; 1153 } 1154 1155 public ScanResult[] newArray(int size) { 1156 return new ScanResult[size]; 1157 } 1158 }; 1159 } 1160