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