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.SystemApi; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 23 import java.util.ArrayList; 24 import java.util.Arrays; 25 import java.util.List; 26 import java.util.Objects; 27 28 /** 29 * Describes information about a detected access point. In addition 30 * to the attributes described here, the supplicant keeps track of 31 * {@code quality}, {@code noise}, and {@code maxbitrate} attributes, 32 * but does not currently report them to external clients. 33 */ 34 public class ScanResult implements Parcelable { 35 /** 36 * The network name. 37 */ 38 public String SSID; 39 40 /** 41 * Ascii encoded SSID. This will replace SSID when we deprecate it. @hide 42 */ 43 public WifiSsid wifiSsid; 44 45 /** 46 * The address of the access point. 47 */ 48 public String BSSID; 49 50 /** 51 * The HESSID from the beacon. 52 * @hide 53 */ 54 public long hessid; 55 56 /** 57 * The ANQP Domain ID from the Hotspot 2.0 Indication element, if present. 58 * @hide 59 */ 60 public int anqpDomainId; 61 62 /* 63 * This field is equivalent to the |flags|, rather than the |capabilities| field 64 * of the per-BSS scan results returned by WPA supplicant. See the definition of 65 * |struct wpa_bss| in wpa_supplicant/bss.h for more details. 66 */ 67 /** 68 * Describes the authentication, key management, and encryption schemes 69 * supported by the access point. 70 */ 71 public String capabilities; 72 73 /** 74 * @hide 75 * No security protocol. 76 */ 77 public static final int PROTOCOL_NONE = 0; 78 /** 79 * @hide 80 * Security protocol type: WPA version 1. 81 */ 82 public static final int PROTOCOL_WPA = 1; 83 /** 84 * @hide 85 * Security protocol type: WPA version 2, also called RSN. 86 */ 87 public static final int PROTOCOL_WPA2 = 2; 88 /** 89 * @hide 90 * Security protocol type: 91 * OSU Server-only authenticated layer 2 Encryption Network. 92 * Used for Hotspot 2.0. 93 */ 94 public static final int PROTOCOL_OSEN = 3; 95 96 /** 97 * @hide 98 * No security key management scheme. 99 */ 100 public static final int KEY_MGMT_NONE = 0; 101 /** 102 * @hide 103 * Security key management scheme: PSK. 104 */ 105 public static final int KEY_MGMT_PSK = 1; 106 /** 107 * @hide 108 * Security key management scheme: EAP. 109 */ 110 public static final int KEY_MGMT_EAP = 2; 111 /** 112 * @hide 113 * Security key management scheme: FT_PSK. 114 */ 115 public static final int KEY_MGMT_FT_PSK = 3; 116 /** 117 * @hide 118 * Security key management scheme: FT_EAP. 119 */ 120 public static final int KEY_MGMT_FT_EAP = 4; 121 /** 122 * @hide 123 * Security key management scheme: PSK_SHA256 124 */ 125 public static final int KEY_MGMT_PSK_SHA256 = 5; 126 /** 127 * @hide 128 * Security key management scheme: EAP_SHA256. 129 */ 130 public static final int KEY_MGMT_EAP_SHA256 = 6; 131 /** 132 * @hide 133 * Security key management scheme: OSEN. 134 * Used for Hotspot 2.0. 135 */ 136 public static final int KEY_MGMT_OSEN = 7; 137 138 /** 139 * @hide 140 * No cipher suite. 141 */ 142 public static final int CIPHER_NONE = 0; 143 /** 144 * @hide 145 * No group addressed, only used for group data cipher. 146 */ 147 public static final int CIPHER_NO_GROUP_ADDRESSED = 1; 148 /** 149 * @hide 150 * Cipher suite: TKIP 151 */ 152 public static final int CIPHER_TKIP = 2; 153 /** 154 * @hide 155 * Cipher suite: CCMP 156 */ 157 public static final int CIPHER_CCMP = 3; 158 159 /** 160 * The detected signal level in dBm, also known as the RSSI. 161 * 162 * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into 163 * an absolute signal level which can be displayed to a user. 164 */ 165 public int level; 166 /** 167 * The primary 20 MHz frequency (in MHz) of the channel over which the client is communicating 168 * with the access point. 169 */ 170 public int frequency; 171 172 /** 173 * AP Channel bandwidth is 20 MHZ 174 */ 175 public static final int CHANNEL_WIDTH_20MHZ = 0; 176 /** 177 * AP Channel bandwidth is 40 MHZ 178 */ 179 public static final int CHANNEL_WIDTH_40MHZ = 1; 180 /** 181 * AP Channel bandwidth is 80 MHZ 182 */ 183 public static final int CHANNEL_WIDTH_80MHZ = 2; 184 /** 185 * AP Channel bandwidth is 160 MHZ 186 */ 187 public static final int CHANNEL_WIDTH_160MHZ = 3; 188 /** 189 * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ 190 */ 191 public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; 192 193 /** 194 * AP Channel bandwidth; one of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ}, 195 * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ} 196 * or {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}. 197 */ 198 public int channelWidth; 199 200 /** 201 * Not used if the AP bandwidth is 20 MHz 202 * If the AP use 40, 80 or 160 MHz, this is the center frequency (in MHz) 203 * if the AP use 80 + 80 MHz, this is the center frequency of the first segment (in MHz) 204 */ 205 public int centerFreq0; 206 207 /** 208 * Only used if the AP bandwidth is 80 + 80 MHz 209 * if the AP use 80 + 80 MHz, this is the center frequency of the second segment (in MHz) 210 */ 211 public int centerFreq1; 212 213 /** 214 * @deprecated use is80211mcResponder() instead 215 * @hide 216 */ 217 public boolean is80211McRTTResponder; 218 219 /** 220 * timestamp in microseconds (since boot) when 221 * this result was last seen. 222 */ 223 public long timestamp; 224 225 /** 226 * Timestamp representing date when this result was last seen, in milliseconds from 1970 227 * {@hide} 228 */ 229 public long seen; 230 231 /** 232 * On devices with multiple hardware radio chains, this class provides metadata about 233 * each radio chain that was used to receive this scan result (probe response or beacon). 234 * {@hide} 235 */ 236 public static class RadioChainInfo { 237 /** Vendor defined id for a radio chain. */ 238 public int id; 239 /** Detected signal level in dBm (also known as the RSSI) on this radio chain. */ 240 public int level; 241 242 @Override toString()243 public String toString() { 244 return "RadioChainInfo: id=" + id + ", level=" + level; 245 } 246 247 @Override equals(Object otherObj)248 public boolean equals(Object otherObj) { 249 if (this == otherObj) { 250 return true; 251 } 252 if (!(otherObj instanceof RadioChainInfo)) { 253 return false; 254 } 255 RadioChainInfo other = (RadioChainInfo) otherObj; 256 return id == other.id && level == other.level; 257 } 258 259 @Override hashCode()260 public int hashCode() { 261 return Objects.hash(id, level); 262 } 263 }; 264 265 /** 266 * Information about the list of the radio chains used to receive this scan result 267 * (probe response or beacon). 268 * 269 * For Example: On devices with 2 hardware radio chains, this list could hold 1 or 2 270 * entries based on whether this scan result was received using one or both the chains. 271 * {@hide} 272 */ 273 public RadioChainInfo[] radioChainInfos; 274 275 /** 276 * Status indicating the scan result does not correspond to a user's saved configuration 277 * @hide 278 * @removed 279 */ 280 @SystemApi 281 public boolean untrusted; 282 283 /** 284 * Number of time autojoin used it 285 * @hide 286 */ 287 public int numUsage; 288 289 /** 290 * The approximate distance to the AP in centimeter, if available. Else 291 * {@link UNSPECIFIED}. 292 * {@hide} 293 */ 294 public int distanceCm; 295 296 /** 297 * The standard deviation of the distance to the access point, if available. 298 * Else {@link UNSPECIFIED}. 299 * {@hide} 300 */ 301 public int distanceSdCm; 302 303 /** {@hide} */ 304 public static final long FLAG_PASSPOINT_NETWORK = 0x0000000000000001; 305 306 /** {@hide} */ 307 public static final long FLAG_80211mc_RESPONDER = 0x0000000000000002; 308 309 /* 310 * These flags are specific to the ScanResult class, and are not related to the |flags| 311 * field of the per-BSS scan results from WPA supplicant. 312 */ 313 /** 314 * Defines flags; such as {@link #FLAG_PASSPOINT_NETWORK}. 315 * {@hide} 316 */ 317 public long flags; 318 319 /** 320 * sets a flag in {@link #flags} field 321 * @param flag flag to set 322 * @hide 323 */ setFlag(long flag)324 public void setFlag(long flag) { 325 flags |= flag; 326 } 327 328 /** 329 * clears a flag in {@link #flags} field 330 * @param flag flag to set 331 * @hide 332 */ clearFlag(long flag)333 public void clearFlag(long flag) { 334 flags &= ~flag; 335 } 336 is80211mcResponder()337 public boolean is80211mcResponder() { 338 return (flags & FLAG_80211mc_RESPONDER) != 0; 339 } 340 isPasspointNetwork()341 public boolean isPasspointNetwork() { 342 return (flags & FLAG_PASSPOINT_NETWORK) != 0; 343 } 344 345 /** 346 * Indicates venue name (such as 'San Francisco Airport') published by access point; only 347 * available on Passpoint network and if published by access point. 348 */ 349 public CharSequence venueName; 350 351 /** 352 * Indicates Passpoint operator name published by access point. 353 */ 354 public CharSequence operatorFriendlyName; 355 356 /** 357 * {@hide} 358 */ 359 public final static int UNSPECIFIED = -1; 360 /** 361 * @hide 362 */ is24GHz()363 public boolean is24GHz() { 364 return ScanResult.is24GHz(frequency); 365 } 366 367 /** 368 * @hide 369 * TODO: makes real freq boundaries 370 */ is24GHz(int freq)371 public static boolean is24GHz(int freq) { 372 return freq > 2400 && freq < 2500; 373 } 374 375 /** 376 * @hide 377 */ is5GHz()378 public boolean is5GHz() { 379 return ScanResult.is5GHz(frequency); 380 } 381 382 /** 383 * @hide 384 * TODO: makes real freq boundaries 385 */ is5GHz(int freq)386 public static boolean is5GHz(int freq) { 387 return freq > 4900 && freq < 5900; 388 } 389 390 /** 391 * @hide 392 * anqp lines from supplicant BSS response 393 */ 394 public List<String> anqpLines; 395 396 /** information elements from beacon 397 * @hide 398 */ 399 public static class InformationElement { 400 public static final int EID_SSID = 0; 401 public static final int EID_SUPPORTED_RATES = 1; 402 public static final int EID_TIM = 5; 403 public static final int EID_BSS_LOAD = 11; 404 public static final int EID_ERP = 42; 405 public static final int EID_HT_CAPABILITIES = 45; 406 public static final int EID_RSN = 48; 407 public static final int EID_EXTENDED_SUPPORTED_RATES = 50; 408 public static final int EID_HT_OPERATION = 61; 409 public static final int EID_INTERWORKING = 107; 410 public static final int EID_ROAMING_CONSORTIUM = 111; 411 public static final int EID_EXTENDED_CAPS = 127; 412 public static final int EID_VHT_CAPABILITIES = 191; 413 public static final int EID_VHT_OPERATION = 192; 414 public static final int EID_VSA = 221; 415 416 public int id; 417 public byte[] bytes; 418 InformationElement()419 public InformationElement() { 420 } 421 InformationElement(InformationElement rhs)422 public InformationElement(InformationElement rhs) { 423 this.id = rhs.id; 424 this.bytes = rhs.bytes.clone(); 425 } 426 } 427 428 /** information elements found in the beacon 429 * @hide 430 */ 431 public InformationElement[] informationElements; 432 433 /** ANQP response elements. 434 * @hide 435 */ 436 public AnqpInformationElement[] anqpElements; 437 438 /** 439 * Flag indicating if this AP is a carrier AP. The determination is based 440 * on the AP's SSID and if AP is using EAP security. 441 * 442 * @hide 443 */ 444 public boolean isCarrierAp; 445 446 /** 447 * The EAP type {@link WifiEnterpriseConfig.Eap} associated with this AP if it is a carrier AP. 448 * 449 * @hide 450 */ 451 public int carrierApEapType; 452 453 /** 454 * The name of the carrier that's associated with this AP if it is a carrier AP. 455 * 456 * @hide 457 */ 458 public String carrierName; 459 460 /** {@hide} */ ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId, byte[] osuProviders, String caps, int level, int frequency, long tsf)461 public ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId, 462 byte[] osuProviders, String caps, int level, int frequency, long tsf) { 463 this.wifiSsid = wifiSsid; 464 this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE; 465 this.BSSID = BSSID; 466 this.hessid = hessid; 467 this.anqpDomainId = anqpDomainId; 468 if (osuProviders != null) { 469 this.anqpElements = new AnqpInformationElement[1]; 470 this.anqpElements[0] = 471 new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID, 472 AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders); 473 } 474 this.capabilities = caps; 475 this.level = level; 476 this.frequency = frequency; 477 this.timestamp = tsf; 478 this.distanceCm = UNSPECIFIED; 479 this.distanceSdCm = UNSPECIFIED; 480 this.channelWidth = UNSPECIFIED; 481 this.centerFreq0 = UNSPECIFIED; 482 this.centerFreq1 = UNSPECIFIED; 483 this.flags = 0; 484 this.isCarrierAp = false; 485 this.carrierApEapType = UNSPECIFIED; 486 this.carrierName = null; 487 this.radioChainInfos = null; 488 } 489 490 /** {@hide} */ ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency, long tsf, int distCm, int distSdCm)491 public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency, 492 long tsf, int distCm, int distSdCm) { 493 this.wifiSsid = wifiSsid; 494 this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE; 495 this.BSSID = BSSID; 496 this.capabilities = caps; 497 this.level = level; 498 this.frequency = frequency; 499 this.timestamp = tsf; 500 this.distanceCm = distCm; 501 this.distanceSdCm = distSdCm; 502 this.channelWidth = UNSPECIFIED; 503 this.centerFreq0 = UNSPECIFIED; 504 this.centerFreq1 = UNSPECIFIED; 505 this.flags = 0; 506 this.isCarrierAp = false; 507 this.carrierApEapType = UNSPECIFIED; 508 this.carrierName = null; 509 this.radioChainInfos = null; 510 } 511 512 /** {@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)513 public ScanResult(String Ssid, String BSSID, long hessid, int anqpDomainId, String caps, 514 int level, int frequency, 515 long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1, 516 boolean is80211McRTTResponder) { 517 this.SSID = Ssid; 518 this.BSSID = BSSID; 519 this.hessid = hessid; 520 this.anqpDomainId = anqpDomainId; 521 this.capabilities = caps; 522 this.level = level; 523 this.frequency = frequency; 524 this.timestamp = tsf; 525 this.distanceCm = distCm; 526 this.distanceSdCm = distSdCm; 527 this.channelWidth = channelWidth; 528 this.centerFreq0 = centerFreq0; 529 this.centerFreq1 = centerFreq1; 530 if (is80211McRTTResponder) { 531 this.flags = FLAG_80211mc_RESPONDER; 532 } else { 533 this.flags = 0; 534 } 535 this.isCarrierAp = false; 536 this.carrierApEapType = UNSPECIFIED; 537 this.carrierName = null; 538 this.radioChainInfos = null; 539 } 540 541 /** {@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)542 public ScanResult(WifiSsid wifiSsid, String Ssid, String BSSID, long hessid, int anqpDomainId, 543 String caps, int level, 544 int frequency, long tsf, int distCm, int distSdCm, int channelWidth, 545 int centerFreq0, int centerFreq1, boolean is80211McRTTResponder) { 546 this(Ssid, BSSID, hessid, anqpDomainId, caps, level, frequency, tsf, distCm, 547 distSdCm, channelWidth, centerFreq0, centerFreq1, is80211McRTTResponder); 548 this.wifiSsid = wifiSsid; 549 } 550 551 /** copy constructor {@hide} */ ScanResult(ScanResult source)552 public ScanResult(ScanResult source) { 553 if (source != null) { 554 wifiSsid = source.wifiSsid; 555 SSID = source.SSID; 556 BSSID = source.BSSID; 557 hessid = source.hessid; 558 anqpDomainId = source.anqpDomainId; 559 informationElements = source.informationElements; 560 anqpElements = source.anqpElements; 561 capabilities = source.capabilities; 562 level = source.level; 563 frequency = source.frequency; 564 channelWidth = source.channelWidth; 565 centerFreq0 = source.centerFreq0; 566 centerFreq1 = source.centerFreq1; 567 timestamp = source.timestamp; 568 distanceCm = source.distanceCm; 569 distanceSdCm = source.distanceSdCm; 570 seen = source.seen; 571 untrusted = source.untrusted; 572 numUsage = source.numUsage; 573 venueName = source.venueName; 574 operatorFriendlyName = source.operatorFriendlyName; 575 flags = source.flags; 576 isCarrierAp = source.isCarrierAp; 577 carrierApEapType = source.carrierApEapType; 578 carrierName = source.carrierName; 579 radioChainInfos = source.radioChainInfos; 580 } 581 } 582 583 /** empty scan result 584 * 585 * {@hide} 586 * */ ScanResult()587 public ScanResult() { 588 } 589 590 @Override toString()591 public String toString() { 592 StringBuffer sb = new StringBuffer(); 593 String none = "<none>"; 594 595 sb.append("SSID: "). 596 append(wifiSsid == null ? WifiSsid.NONE : wifiSsid). 597 append(", BSSID: "). 598 append(BSSID == null ? none : BSSID). 599 append(", capabilities: "). 600 append(capabilities == null ? none : capabilities). 601 append(", level: "). 602 append(level). 603 append(", frequency: "). 604 append(frequency). 605 append(", timestamp: "). 606 append(timestamp); 607 608 sb.append(", distance: ").append((distanceCm != UNSPECIFIED ? distanceCm : "?")). 609 append("(cm)"); 610 sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")). 611 append("(cm)"); 612 613 sb.append(", passpoint: "); 614 sb.append(((flags & FLAG_PASSPOINT_NETWORK) != 0) ? "yes" : "no"); 615 sb.append(", ChannelBandwidth: ").append(channelWidth); 616 sb.append(", centerFreq0: ").append(centerFreq0); 617 sb.append(", centerFreq1: ").append(centerFreq1); 618 sb.append(", 80211mcResponder: "); 619 sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported"); 620 sb.append(", Carrier AP: ").append(isCarrierAp ? "yes" : "no"); 621 sb.append(", Carrier AP EAP Type: ").append(carrierApEapType); 622 sb.append(", Carrier name: ").append(carrierName); 623 sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos)); 624 return sb.toString(); 625 } 626 627 /** Implement the Parcelable interface {@hide} */ describeContents()628 public int describeContents() { 629 return 0; 630 } 631 632 /** Implement the Parcelable interface {@hide} */ writeToParcel(Parcel dest, int flags)633 public void writeToParcel(Parcel dest, int flags) { 634 if (wifiSsid != null) { 635 dest.writeInt(1); 636 wifiSsid.writeToParcel(dest, flags); 637 } else { 638 dest.writeInt(0); 639 } 640 dest.writeString(SSID); 641 dest.writeString(BSSID); 642 dest.writeLong(hessid); 643 dest.writeInt(anqpDomainId); 644 dest.writeString(capabilities); 645 dest.writeInt(level); 646 dest.writeInt(frequency); 647 dest.writeLong(timestamp); 648 dest.writeInt(distanceCm); 649 dest.writeInt(distanceSdCm); 650 dest.writeInt(channelWidth); 651 dest.writeInt(centerFreq0); 652 dest.writeInt(centerFreq1); 653 dest.writeLong(seen); 654 dest.writeInt(untrusted ? 1 : 0); 655 dest.writeInt(numUsage); 656 dest.writeString((venueName != null) ? venueName.toString() : ""); 657 dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : ""); 658 dest.writeLong(this.flags); 659 660 if (informationElements != null) { 661 dest.writeInt(informationElements.length); 662 for (int i = 0; i < informationElements.length; i++) { 663 dest.writeInt(informationElements[i].id); 664 dest.writeInt(informationElements[i].bytes.length); 665 dest.writeByteArray(informationElements[i].bytes); 666 } 667 } else { 668 dest.writeInt(0); 669 } 670 671 if (anqpLines != null) { 672 dest.writeInt(anqpLines.size()); 673 for (int i = 0; i < anqpLines.size(); i++) { 674 dest.writeString(anqpLines.get(i)); 675 } 676 } 677 else { 678 dest.writeInt(0); 679 } 680 if (anqpElements != null) { 681 dest.writeInt(anqpElements.length); 682 for (AnqpInformationElement element : anqpElements) { 683 dest.writeInt(element.getVendorId()); 684 dest.writeInt(element.getElementId()); 685 dest.writeInt(element.getPayload().length); 686 dest.writeByteArray(element.getPayload()); 687 } 688 } else { 689 dest.writeInt(0); 690 } 691 dest.writeInt(isCarrierAp ? 1 : 0); 692 dest.writeInt(carrierApEapType); 693 dest.writeString(carrierName); 694 695 if (radioChainInfos != null) { 696 dest.writeInt(radioChainInfos.length); 697 for (int i = 0; i < radioChainInfos.length; i++) { 698 dest.writeInt(radioChainInfos[i].id); 699 dest.writeInt(radioChainInfos[i].level); 700 } 701 } else { 702 dest.writeInt(0); 703 } 704 } 705 706 /** Implement the Parcelable interface {@hide} */ 707 public static final Creator<ScanResult> CREATOR = 708 new Creator<ScanResult>() { 709 public ScanResult createFromParcel(Parcel in) { 710 WifiSsid wifiSsid = null; 711 if (in.readInt() == 1) { 712 wifiSsid = WifiSsid.CREATOR.createFromParcel(in); 713 } 714 ScanResult sr = new ScanResult( 715 wifiSsid, 716 in.readString(), /* SSID */ 717 in.readString(), /* BSSID */ 718 in.readLong(), /* HESSID */ 719 in.readInt(), /* ANQP Domain ID */ 720 in.readString(), /* capabilities */ 721 in.readInt(), /* level */ 722 in.readInt(), /* frequency */ 723 in.readLong(), /* timestamp */ 724 in.readInt(), /* distanceCm */ 725 in.readInt(), /* distanceSdCm */ 726 in.readInt(), /* channelWidth */ 727 in.readInt(), /* centerFreq0 */ 728 in.readInt(), /* centerFreq1 */ 729 false /* rtt responder, 730 fixed with flags below */ 731 ); 732 733 sr.seen = in.readLong(); 734 sr.untrusted = in.readInt() != 0; 735 sr.numUsage = in.readInt(); 736 sr.venueName = in.readString(); 737 sr.operatorFriendlyName = in.readString(); 738 sr.flags = in.readLong(); 739 int n = in.readInt(); 740 if (n != 0) { 741 sr.informationElements = new InformationElement[n]; 742 for (int i = 0; i < n; i++) { 743 sr.informationElements[i] = new InformationElement(); 744 sr.informationElements[i].id = in.readInt(); 745 int len = in.readInt(); 746 sr.informationElements[i].bytes = new byte[len]; 747 in.readByteArray(sr.informationElements[i].bytes); 748 } 749 } 750 751 n = in.readInt(); 752 if (n != 0) { 753 sr.anqpLines = new ArrayList<String>(); 754 for (int i = 0; i < n; i++) { 755 sr.anqpLines.add(in.readString()); 756 } 757 } 758 n = in.readInt(); 759 if (n != 0) { 760 sr.anqpElements = new AnqpInformationElement[n]; 761 for (int i = 0; i < n; i++) { 762 int vendorId = in.readInt(); 763 int elementId = in.readInt(); 764 int len = in.readInt(); 765 byte[] payload = new byte[len]; 766 in.readByteArray(payload); 767 sr.anqpElements[i] = 768 new AnqpInformationElement(vendorId, elementId, payload); 769 } 770 } 771 sr.isCarrierAp = in.readInt() != 0; 772 sr.carrierApEapType = in.readInt(); 773 sr.carrierName = in.readString(); 774 n = in.readInt(); 775 if (n != 0) { 776 sr.radioChainInfos = new RadioChainInfo[n]; 777 for (int i = 0; i < n; i++) { 778 sr.radioChainInfos[i] = new RadioChainInfo(); 779 sr.radioChainInfos[i].id = in.readInt(); 780 sr.radioChainInfos[i].level = in.readInt(); 781 } 782 } 783 return sr; 784 } 785 786 public ScanResult[] newArray(int size) { 787 return new ScanResult[size]; 788 } 789 }; 790 } 791