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      */
    266     @SystemApi
    267     public boolean untrusted;
    268 
    269     /**
    270      * Number of time we connected to it
    271      * @hide
    272      */
    273     public int numConnection;
    274 
    275     /**
    276      * Number of time autojoin used it
    277      * @hide
    278      */
    279     public int numUsage;
    280 
    281     /**
    282      * The approximate distance to the AP in centimeter, if available.  Else
    283      * {@link UNSPECIFIED}.
    284      * {@hide}
    285      */
    286     public int distanceCm;
    287 
    288     /**
    289      * The standard deviation of the distance to the access point, if available.
    290      * Else {@link UNSPECIFIED}.
    291      * {@hide}
    292      */
    293     public int distanceSdCm;
    294 
    295     /** {@hide} */
    296     public static final long FLAG_PASSPOINT_NETWORK               = 0x0000000000000001;
    297 
    298     /** {@hide} */
    299     public static final long FLAG_80211mc_RESPONDER               = 0x0000000000000002;
    300 
    301     /*
    302      * These flags are specific to the ScanResult class, and are not related to the |flags|
    303      * field of the per-BSS scan results from WPA supplicant.
    304      */
    305     /**
    306      * Defines flags; such as {@link #FLAG_PASSPOINT_NETWORK}.
    307      * {@hide}
    308      */
    309     public long flags;
    310 
    311     /**
    312      * sets a flag in {@link #flags} field
    313      * @param flag flag to set
    314      * @hide
    315      */
    316     public void setFlag(long flag) {
    317         flags |= flag;
    318     }
    319 
    320     /**
    321      * clears a flag in {@link #flags} field
    322      * @param flag flag to set
    323      * @hide
    324      */
    325     public void clearFlag(long flag) {
    326         flags &= ~flag;
    327     }
    328 
    329     public boolean is80211mcResponder() {
    330         return (flags & FLAG_80211mc_RESPONDER) != 0;
    331     }
    332 
    333     public boolean isPasspointNetwork() {
    334         return (flags & FLAG_PASSPOINT_NETWORK) != 0;
    335     }
    336 
    337     /**
    338      * Indicates venue name (such as 'San Francisco Airport') published by access point; only
    339      * available on Passpoint network and if published by access point.
    340      */
    341     public CharSequence venueName;
    342 
    343     /**
    344      * Indicates Passpoint operator name published by access point.
    345      */
    346     public CharSequence operatorFriendlyName;
    347 
    348     /**
    349      * {@hide}
    350      */
    351     public final static int UNSPECIFIED = -1;
    352     /**
    353      * @hide
    354      */
    355     public boolean is24GHz() {
    356         return ScanResult.is24GHz(frequency);
    357     }
    358 
    359     /**
    360      * @hide
    361      * TODO: makes real freq boundaries
    362      */
    363     public static boolean is24GHz(int freq) {
    364         return freq > 2400 && freq < 2500;
    365     }
    366 
    367     /**
    368      * @hide
    369      */
    370     public boolean is5GHz() {
    371         return ScanResult.is5GHz(frequency);
    372     }
    373 
    374     /**
    375      * @hide
    376      * TODO: makes real freq boundaries
    377      */
    378     public static boolean is5GHz(int freq) {
    379         return freq > 4900 && freq < 5900;
    380     }
    381 
    382     /**
    383      *  @hide
    384      * anqp lines from supplicant BSS response
    385      */
    386     public List<String> anqpLines;
    387 
    388     /**
    389      *  @hide
    390      * storing the raw bytes of full result IEs
    391      **/
    392     public byte[] bytes;
    393 
    394     /** information elements from beacon
    395      * @hide
    396      */
    397     public static class InformationElement {
    398         public static final int EID_SSID = 0;
    399         public static final int EID_SUPPORTED_RATES = 1;
    400         public static final int EID_TIM = 5;
    401         public static final int EID_BSS_LOAD = 11;
    402         public static final int EID_ERP = 42;
    403         public static final int EID_RSN = 48;
    404         public static final int EID_EXTENDED_SUPPORTED_RATES = 50;
    405         public static final int EID_HT_OPERATION = 61;
    406         public static final int EID_INTERWORKING = 107;
    407         public static final int EID_ROAMING_CONSORTIUM = 111;
    408         public static final int EID_EXTENDED_CAPS = 127;
    409         public static final int EID_VHT_OPERATION = 192;
    410         public static final int EID_VSA = 221;
    411 
    412         public int id;
    413         public byte[] bytes;
    414 
    415         public InformationElement() {
    416         }
    417 
    418         public InformationElement(InformationElement rhs) {
    419             this.id = rhs.id;
    420             this.bytes = rhs.bytes.clone();
    421         }
    422     }
    423 
    424     /** information elements found in the beacon
    425      * @hide
    426      */
    427     public InformationElement[] informationElements;
    428 
    429     /** ANQP response elements.
    430      * @hide
    431      */
    432     public AnqpInformationElement[] anqpElements;
    433 
    434     /** {@hide} */
    435     public ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId,
    436             byte[] osuProviders, String caps, int level, int frequency, long tsf) {
    437         this.wifiSsid = wifiSsid;
    438         this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
    439         this.BSSID = BSSID;
    440         this.hessid = hessid;
    441         this.anqpDomainId = anqpDomainId;
    442         if (osuProviders != null) {
    443             this.anqpElements = new AnqpInformationElement[1];
    444             this.anqpElements[0] =
    445                     new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID,
    446                             AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders);
    447         }
    448         this.capabilities = caps;
    449         this.level = level;
    450         this.frequency = frequency;
    451         this.timestamp = tsf;
    452         this.distanceCm = UNSPECIFIED;
    453         this.distanceSdCm = UNSPECIFIED;
    454         this.channelWidth = UNSPECIFIED;
    455         this.centerFreq0 = UNSPECIFIED;
    456         this.centerFreq1 = UNSPECIFIED;
    457         this.flags = 0;
    458     }
    459 
    460     /** {@hide} */
    461     public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency,
    462             long tsf, int distCm, int distSdCm) {
    463         this.wifiSsid = wifiSsid;
    464         this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
    465         this.BSSID = BSSID;
    466         this.capabilities = caps;
    467         this.level = level;
    468         this.frequency = frequency;
    469         this.timestamp = tsf;
    470         this.distanceCm = distCm;
    471         this.distanceSdCm = distSdCm;
    472         this.channelWidth = UNSPECIFIED;
    473         this.centerFreq0 = UNSPECIFIED;
    474         this.centerFreq1 = UNSPECIFIED;
    475         this.flags = 0;
    476     }
    477 
    478     /** {@hide} */
    479     public ScanResult(String Ssid, String BSSID, long hessid, int anqpDomainId, String caps,
    480             int level, int frequency,
    481             long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1,
    482             boolean is80211McRTTResponder) {
    483         this.SSID = Ssid;
    484         this.BSSID = BSSID;
    485         this.hessid = hessid;
    486         this.anqpDomainId = anqpDomainId;
    487         this.capabilities = caps;
    488         this.level = level;
    489         this.frequency = frequency;
    490         this.timestamp = tsf;
    491         this.distanceCm = distCm;
    492         this.distanceSdCm = distSdCm;
    493         this.channelWidth = channelWidth;
    494         this.centerFreq0 = centerFreq0;
    495         this.centerFreq1 = centerFreq1;
    496         if (is80211McRTTResponder) {
    497             this.flags = FLAG_80211mc_RESPONDER;
    498         } else {
    499             this.flags = 0;
    500         }
    501     }
    502 
    503     /** {@hide} */
    504     public ScanResult(WifiSsid wifiSsid, String Ssid, String BSSID, long hessid, int anqpDomainId,
    505                   String caps, int level,
    506                   int frequency, long tsf, int distCm, int distSdCm, int channelWidth,
    507                   int centerFreq0, int centerFreq1, boolean is80211McRTTResponder) {
    508         this(Ssid, BSSID, hessid, anqpDomainId, caps, level, frequency, tsf, distCm,
    509                 distSdCm, channelWidth, centerFreq0, centerFreq1, is80211McRTTResponder);
    510         this.wifiSsid = wifiSsid;
    511     }
    512 
    513     /** copy constructor {@hide} */
    514     public ScanResult(ScanResult source) {
    515         if (source != null) {
    516             wifiSsid = source.wifiSsid;
    517             SSID = source.SSID;
    518             BSSID = source.BSSID;
    519             hessid = source.hessid;
    520             anqpDomainId = source.anqpDomainId;
    521             informationElements = source.informationElements;
    522             anqpElements = source.anqpElements;
    523             capabilities = source.capabilities;
    524             level = source.level;
    525             frequency = source.frequency;
    526             channelWidth = source.channelWidth;
    527             centerFreq0 = source.centerFreq0;
    528             centerFreq1 = source.centerFreq1;
    529             timestamp = source.timestamp;
    530             distanceCm = source.distanceCm;
    531             distanceSdCm = source.distanceSdCm;
    532             seen = source.seen;
    533             untrusted = source.untrusted;
    534             numConnection = source.numConnection;
    535             numUsage = source.numUsage;
    536             numIpConfigFailures = source.numIpConfigFailures;
    537             venueName = source.venueName;
    538             operatorFriendlyName = source.operatorFriendlyName;
    539             flags = source.flags;
    540         }
    541     }
    542 
    543     /** empty scan result
    544      *
    545      * {@hide}
    546      * */
    547     public ScanResult() {
    548     }
    549 
    550     @Override
    551     public String toString() {
    552         StringBuffer sb = new StringBuffer();
    553         String none = "<none>";
    554 
    555         sb.append("SSID: ").
    556             append(wifiSsid == null ? WifiSsid.NONE : wifiSsid).
    557             append(", BSSID: ").
    558             append(BSSID == null ? none : BSSID).
    559             append(", capabilities: ").
    560             append(capabilities == null ? none : capabilities).
    561             append(", level: ").
    562             append(level).
    563             append(", frequency: ").
    564             append(frequency).
    565             append(", timestamp: ").
    566             append(timestamp);
    567 
    568         sb.append(", distance: ").append((distanceCm != UNSPECIFIED ? distanceCm : "?")).
    569                 append("(cm)");
    570         sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")).
    571                 append("(cm)");
    572 
    573         sb.append(", passpoint: ");
    574         sb.append(((flags & FLAG_PASSPOINT_NETWORK) != 0) ? "yes" : "no");
    575         sb.append(", ChannelBandwidth: ").append(channelWidth);
    576         sb.append(", centerFreq0: ").append(centerFreq0);
    577         sb.append(", centerFreq1: ").append(centerFreq1);
    578         sb.append(", 80211mcResponder: ");
    579         sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported");
    580         return sb.toString();
    581     }
    582 
    583     /** Implement the Parcelable interface {@hide} */
    584     public int describeContents() {
    585         return 0;
    586     }
    587 
    588     /** Implement the Parcelable interface {@hide} */
    589     public void writeToParcel(Parcel dest, int flags) {
    590         if (wifiSsid != null) {
    591             dest.writeInt(1);
    592             wifiSsid.writeToParcel(dest, flags);
    593         } else {
    594             dest.writeInt(0);
    595         }
    596         dest.writeString(SSID);
    597         dest.writeString(BSSID);
    598         dest.writeLong(hessid);
    599         dest.writeInt(anqpDomainId);
    600         dest.writeString(capabilities);
    601         dest.writeInt(level);
    602         dest.writeInt(frequency);
    603         dest.writeLong(timestamp);
    604         dest.writeInt(distanceCm);
    605         dest.writeInt(distanceSdCm);
    606         dest.writeInt(channelWidth);
    607         dest.writeInt(centerFreq0);
    608         dest.writeInt(centerFreq1);
    609         dest.writeLong(seen);
    610         dest.writeInt(untrusted ? 1 : 0);
    611         dest.writeInt(numConnection);
    612         dest.writeInt(numUsage);
    613         dest.writeInt(numIpConfigFailures);
    614         dest.writeString((venueName != null) ? venueName.toString() : "");
    615         dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : "");
    616         dest.writeLong(this.flags);
    617 
    618         if (informationElements != null) {
    619             dest.writeInt(informationElements.length);
    620             for (int i = 0; i < informationElements.length; i++) {
    621                 dest.writeInt(informationElements[i].id);
    622                 dest.writeInt(informationElements[i].bytes.length);
    623                 dest.writeByteArray(informationElements[i].bytes);
    624             }
    625         } else {
    626             dest.writeInt(0);
    627         }
    628 
    629         if (anqpLines != null) {
    630             dest.writeInt(anqpLines.size());
    631             for (int i = 0; i < anqpLines.size(); i++) {
    632                 dest.writeString(anqpLines.get(i));
    633             }
    634         }
    635         else {
    636             dest.writeInt(0);
    637         }
    638         if (anqpElements != null) {
    639             dest.writeInt(anqpElements.length);
    640             for (AnqpInformationElement element : anqpElements) {
    641                 dest.writeInt(element.getVendorId());
    642                 dest.writeInt(element.getElementId());
    643                 dest.writeInt(element.getPayload().length);
    644                 dest.writeByteArray(element.getPayload());
    645             }
    646         } else {
    647             dest.writeInt(0);
    648         }
    649     }
    650 
    651     /** Implement the Parcelable interface {@hide} */
    652     public static final Creator<ScanResult> CREATOR =
    653         new Creator<ScanResult>() {
    654             public ScanResult createFromParcel(Parcel in) {
    655                 WifiSsid wifiSsid = null;
    656                 if (in.readInt() == 1) {
    657                     wifiSsid = WifiSsid.CREATOR.createFromParcel(in);
    658                 }
    659                 ScanResult sr = new ScanResult(
    660                         wifiSsid,
    661                         in.readString(),                    /* SSID  */
    662                         in.readString(),                    /* BSSID */
    663                         in.readLong(),                      /* HESSID */
    664                         in.readInt(),                       /* ANQP Domain ID */
    665                         in.readString(),                    /* capabilities */
    666                         in.readInt(),                       /* level */
    667                         in.readInt(),                       /* frequency */
    668                         in.readLong(),                      /* timestamp */
    669                         in.readInt(),                       /* distanceCm */
    670                         in.readInt(),                       /* distanceSdCm */
    671                         in.readInt(),                       /* channelWidth */
    672                         in.readInt(),                       /* centerFreq0 */
    673                         in.readInt(),                       /* centerFreq1 */
    674                         false                               /* rtt responder,
    675                                                                fixed with flags below */
    676                 );
    677 
    678                 sr.seen = in.readLong();
    679                 sr.untrusted = in.readInt() != 0;
    680                 sr.numConnection = in.readInt();
    681                 sr.numUsage = in.readInt();
    682                 sr.numIpConfigFailures = in.readInt();
    683                 sr.venueName = in.readString();
    684                 sr.operatorFriendlyName = in.readString();
    685                 sr.flags = in.readLong();
    686                 int n = in.readInt();
    687                 if (n != 0) {
    688                     sr.informationElements = new InformationElement[n];
    689                     for (int i = 0; i < n; i++) {
    690                         sr.informationElements[i] = new InformationElement();
    691                         sr.informationElements[i].id = in.readInt();
    692                         int len = in.readInt();
    693                         sr.informationElements[i].bytes = new byte[len];
    694                         in.readByteArray(sr.informationElements[i].bytes);
    695                     }
    696                 }
    697 
    698                 n = in.readInt();
    699                 if (n != 0) {
    700                     sr.anqpLines = new ArrayList<String>();
    701                     for (int i = 0; i < n; i++) {
    702                         sr.anqpLines.add(in.readString());
    703                     }
    704                 }
    705                 n = in.readInt();
    706                 if (n != 0) {
    707                     sr.anqpElements = new AnqpInformationElement[n];
    708                     for (int i = 0; i < n; i++) {
    709                         int vendorId = in.readInt();
    710                         int elementId = in.readInt();
    711                         int len = in.readInt();
    712                         byte[] payload = new byte[len];
    713                         in.readByteArray(payload);
    714                         sr.anqpElements[i] =
    715                                 new AnqpInformationElement(vendorId, elementId, payload);
    716                     }
    717                 }
    718                 return sr;
    719             }
    720 
    721             public ScanResult[] newArray(int size) {
    722                 return new ScanResult[size];
    723             }
    724         };
    725 }
    726