• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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