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