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