• 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.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.annotation.IntRange;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.SystemApi;
25 import android.compat.annotation.UnsupportedAppUsage;
26 import android.net.MacAddress;
27 import android.net.wifi.WifiAnnotations.ChannelWidth;
28 import android.net.wifi.WifiAnnotations.WifiStandard;
29 import android.net.wifi.util.ScanResultUtil;
30 import android.os.Build;
31 import android.os.Parcel;
32 import android.os.Parcelable;
33 import android.util.Log;
34 
35 import androidx.annotation.Keep;
36 
37 import com.android.modules.utils.build.SdkLevel;
38 import com.android.wifi.flags.Flags;
39 
40 import java.lang.annotation.Retention;
41 import java.lang.annotation.RetentionPolicy;
42 import java.nio.ByteBuffer;
43 import java.util.ArrayList;
44 import java.util.Arrays;
45 import java.util.Collections;
46 import java.util.List;
47 import java.util.Objects;
48 
49 /**
50  * Describes information about a detected access point. In addition
51  * to the attributes described here, the supplicant keeps track of
52  * {@code quality}, {@code noise}, and {@code maxbitrate} attributes,
53  * but does not currently report them to external clients.
54  */
55 public final class ScanResult implements Parcelable {
56 
57     private static final String TAG = "ScanResult";
58     /**
59      * The network name.
60      *
61      * @deprecated Use {@link #getWifiSsid()} instead.
62      */
63     @Deprecated
64     public String SSID;
65 
66     /**
67      * Ascii encoded SSID. This will replace SSID when we deprecate it. @hide
68      *
69      * @deprecated Use {@link #getWifiSsid()} instead.
70      */
71     @Deprecated
72     // TODO(b/231433398): add maxTargetSdk = Build.VERSION_CODES.S
73     @UnsupportedAppUsage(publicAlternatives = "{@link #getWifiSsid()}")
74     public WifiSsid wifiSsid;
75 
76     /**
77      * Set the SSID of the access point.
78      * @hide
79      */
80     @SystemApi
setWifiSsid(@onNull WifiSsid ssid)81     public void setWifiSsid(@NonNull WifiSsid ssid) {
82         wifiSsid = ssid;
83         CharSequence utf8Text = wifiSsid.getUtf8Text();
84         SSID = utf8Text != null ? utf8Text.toString() : WifiManager.UNKNOWN_SSID;
85     }
86 
87     /**
88      * The SSID of the access point.
89      */
90     @Nullable
getWifiSsid()91     public WifiSsid getWifiSsid() {
92         return wifiSsid;
93     }
94 
95     /**
96      * The address of the access point.
97      */
98     public String BSSID;
99 
100     /**
101      * The Multi-Link Device (MLD) address of the access point.
102      * Only applicable for Wi-Fi 7 access points, null otherwise.
103      */
104     private MacAddress mApMldMacAddress;
105 
106     /**
107      * Return the access point Multi-Link Device (MLD) MAC Address for Wi-Fi 7 access points.
108      * i.e. {@link #getWifiStandard()} returns {@link #WIFI_STANDARD_11BE}.
109      *
110      * @return MLD MAC Address for access point if exists (Wi-Fi 7 access points), null otherwise.
111      */
112     @Nullable
getApMldMacAddress()113     public MacAddress getApMldMacAddress() {
114         return mApMldMacAddress;
115     }
116 
117     /**
118      * Set the access point Multi-Link Device (MLD) MAC Address.
119      * @hide
120      */
setApMldMacAddress(@ullable MacAddress address)121     public void setApMldMacAddress(@Nullable MacAddress address) {
122         mApMldMacAddress = address;
123     }
124 
125     /**
126      * The Multi-Link Operation (MLO) link id for the access point.
127      * Only applicable for Wi-Fi 7 access points.
128      */
129     private int mApMloLinkId = MloLink.INVALID_MLO_LINK_ID;
130 
131     /**
132      * Return the access point Multi-Link Operation (MLO) link-id for Wi-Fi 7 access points.
133      * i.e. when {@link #getWifiStandard()} returns {@link #WIFI_STANDARD_11BE}, otherwise return
134      * {@link MloLink#INVALID_MLO_LINK_ID}.
135      *
136      * Valid values are 0-15 as described in IEEE 802.11be Specification, section 9.4.2.295b.2.
137      *
138      * @return {@link MloLink#INVALID_MLO_LINK_ID} or a valid value (0-15).
139      */
140     @IntRange(from = MloLink.INVALID_MLO_LINK_ID, to = MloLink.MAX_MLO_LINK_ID)
getApMloLinkId()141     public int getApMloLinkId() {
142         return mApMloLinkId;
143     }
144 
145     /**
146      * Sets the access point Multi-Link Operation (MLO) link-id
147      * @hide
148      */
setApMloLinkId(int linkId)149     public void setApMloLinkId(int linkId) {
150         mApMloLinkId = linkId;
151     }
152 
153     /**
154      * The Multi-Link Operation (MLO) affiliated Links.
155      * Only applicable for Wi-Fi 7 access points.
156      * Note: the list of links includes the access point for this ScanResult.
157      */
158     private List<MloLink> mAffiliatedMloLinks = Collections.emptyList();
159 
160     /**
161      * Return the Multi-Link Operation (MLO) affiliated Links for Wi-Fi 7 access points.
162      * i.e. when {@link #getWifiStandard()} returns {@link #WIFI_STANDARD_11BE}.
163      *
164      * @return List of affiliated MLO links, or an empty list if access point is not Wi-Fi 7
165      */
166     @NonNull
getAffiliatedMloLinks()167     public List<MloLink> getAffiliatedMloLinks() {
168         return new ArrayList<MloLink>(mAffiliatedMloLinks);
169     }
170 
171     /**
172      * Set the Multi-Link Operation (MLO) affiliated Links.
173      * Only applicable for Wi-Fi 7 access points.
174      *
175      * @hide
176      */
setAffiliatedMloLinks(@onNull List<MloLink> links)177     public void setAffiliatedMloLinks(@NonNull List<MloLink> links) {
178         mAffiliatedMloLinks = new ArrayList<MloLink>(links);
179     }
180 
181     /**
182      * The HESSID from the beacon.
183      * @hide
184      */
185     @UnsupportedAppUsage
186     public long hessid;
187 
188     /**
189      * The ANQP Domain ID from the Hotspot 2.0 Indication element, if present.
190      * @hide
191      */
192     @UnsupportedAppUsage
193     public int anqpDomainId;
194 
195     /*
196      * This field is equivalent to the |flags|, rather than the |capabilities| field
197      * of the per-BSS scan results returned by WPA supplicant. See the definition of
198      * |struct wpa_bss| in wpa_supplicant/bss.h for more details.
199      */
200     /**
201      * Describes the authentication, key management, and encryption schemes
202      * supported by the access point.
203      */
204     public String capabilities;
205 
206     /**
207      * The interface name on which the scan result was received.
208      * @hide
209      */
210     public String ifaceName;
211 
212     /**
213      * @hide
214      * No security protocol.
215      */
216     @SystemApi
217     public static final int PROTOCOL_NONE = 0;
218     /**
219      * @hide
220      * Security protocol type: WPA version 1.
221      */
222     @SystemApi
223     public static final int PROTOCOL_WPA = 1;
224     /**
225      * @hide
226      * Security protocol type: RSN, for WPA version 2, and version 3.
227      */
228     @SystemApi
229     public static final int PROTOCOL_RSN = 2;
230     /**
231      * @hide
232      * Security protocol type:
233      * OSU Server-only authenticated layer 2 Encryption Network.
234      * Used for Hotspot 2.0.
235      */
236     @SystemApi
237     public static final int PROTOCOL_OSEN = 3;
238 
239     /**
240      * @hide
241      * Security protocol type: WAPI.
242      */
243     @SystemApi
244     public static final int PROTOCOL_WAPI = 4;
245 
246     /**
247      * @hide
248      * No security key management scheme.
249      */
250     @SystemApi
251     public static final int KEY_MGMT_NONE = 0;
252     /**
253      * @hide
254      * Security key management scheme: PSK.
255      */
256     @SystemApi
257     public static final int KEY_MGMT_PSK = 1;
258     /**
259      * @hide
260      * Security key management scheme: EAP.
261      */
262     @SystemApi
263     public static final int KEY_MGMT_EAP = 2;
264     /**
265      * @hide
266      * Security key management scheme: FT_PSK.
267      */
268     @SystemApi
269     public static final int KEY_MGMT_FT_PSK = 3;
270     /**
271      * @hide
272      * Security key management scheme: FT_EAP.
273      */
274     @SystemApi
275     public static final int KEY_MGMT_FT_EAP = 4;
276     /**
277      * @hide
278      * Security key management scheme: PSK_SHA256
279      */
280     @SystemApi
281     public static final int KEY_MGMT_PSK_SHA256 = 5;
282     /**
283      * @hide
284      * Security key management scheme: EAP_SHA256.
285      */
286     @SystemApi
287     public static final int KEY_MGMT_EAP_SHA256 = 6;
288     /**
289      * @hide
290      * Security key management scheme: OSEN.
291      * Used for Hotspot 2.0.
292      */
293     @SystemApi
294     public static final int KEY_MGMT_OSEN = 7;
295      /**
296      * @hide
297      * Security key management scheme: SAE.
298      */
299     @SystemApi
300     public static final int KEY_MGMT_SAE = 8;
301     /**
302      * @hide
303      * Security key management scheme: OWE.
304      */
305     @SystemApi
306     public static final int KEY_MGMT_OWE = 9;
307     /**
308      * @hide
309      * Security key management scheme: SUITE_B_192.
310      */
311     @SystemApi
312     public static final int KEY_MGMT_EAP_SUITE_B_192 = 10;
313     /**
314      * @hide
315      * Security key management scheme: FT_SAE.
316      */
317     @SystemApi
318     public static final int KEY_MGMT_FT_SAE = 11;
319     /**
320      * @hide
321      * Security key management scheme: OWE in transition mode.
322      */
323     @SystemApi
324     public static final int KEY_MGMT_OWE_TRANSITION = 12;
325     /**
326      * @hide
327      * Security key management scheme: WAPI_PSK.
328      */
329     @SystemApi
330     public static final int KEY_MGMT_WAPI_PSK = 13;
331     /**
332      * @hide
333      * Security key management scheme: WAPI_CERT.
334      */
335     @SystemApi
336     public static final int KEY_MGMT_WAPI_CERT = 14;
337 
338     /**
339      * @hide
340      * Security key management scheme: FILS_SHA256.
341      */
342     public static final int KEY_MGMT_FILS_SHA256 = 15;
343     /**
344      * @hide
345      * Security key management scheme: FILS_SHA384.
346      */
347     public static final int KEY_MGMT_FILS_SHA384 = 16;
348     /**
349      * @hide
350      * Security key management scheme: DPP.
351      */
352     public static final int KEY_MGMT_DPP = 17;
353     /**
354      * @hide
355      * Security key management scheme: SAE_EXT_KEY.
356      */
357     public static final int KEY_MGMT_SAE_EXT_KEY = 18;
358     /**
359      * @hide
360      * Security key management scheme: FT_SAE_EXT_KEY.
361      */
362     public static final int KEY_MGMT_FT_SAE_EXT_KEY = 19;
363     /**
364      * @hide
365      * Security key management scheme: PASN.
366      */
367     public static final int KEY_MGMT_PASN = 20;
368 
369     /**
370      * Security key management scheme: FT authentication negotiated over IEEE Std 802.1X using
371      * SHA-384.
372      * @hide
373      */
374     public static final int KEY_MGMT_EAP_FT_SHA384 = 21;
375     /**
376      * Security key management scheme: FT authentication using PSK (SHA-384).
377      * @hide
378      */
379     public static final int KEY_MGMT_FT_PSK_SHA384 = 22;
380     /**
381      * @hide
382      * Security key management scheme: any unknown AKM.
383      */
384     public static final int KEY_MGMT_UNKNOWN = 23;
385     /**
386      * @hide
387      * No cipher suite.
388      */
389     @SystemApi
390     public static final int CIPHER_NONE = 0;
391     /**
392      * @hide
393      * No group addressed, only used for group data cipher.
394      */
395     @SystemApi
396     public static final int CIPHER_NO_GROUP_ADDRESSED = 1;
397     /**
398      * @hide
399      * Cipher suite: TKIP
400      */
401     @SystemApi
402     public static final int CIPHER_TKIP = 2;
403     /**
404      * @hide
405      * Cipher suite: CCMP
406      */
407     @SystemApi
408     public static final int CIPHER_CCMP = 3;
409     /**
410      * @hide
411      * Cipher suite: GCMP
412      */
413     @SystemApi
414     public static final int CIPHER_GCMP_256 = 4;
415     /**
416      * @hide
417      * Cipher suite: SMS4
418      */
419     @SystemApi
420     public static final int CIPHER_SMS4 = 5;
421     /**
422      * @hide
423      * Cipher suite: GCMP_128
424      */
425     @SystemApi
426     public static final int CIPHER_GCMP_128 = 6;
427     /**
428      * @hide
429      * Cipher suite: BIP_GMAC_128
430      */
431     @SystemApi
432     public static final int CIPHER_BIP_GMAC_128 = 7;
433     /**
434      * @hide
435      * Cipher suite: BIP_GMAC_256
436      */
437     @SystemApi
438     public static final int CIPHER_BIP_GMAC_256 = 8;
439     /**
440      * @hide
441      * Cipher suite: BIP_CMAC_256
442      */
443     @SystemApi
444     public static final int CIPHER_BIP_CMAC_256 = 9;
445     /**
446      * @hide
447      * Cipher suite: CCMP_256
448      */
449     public static final int CIPHER_CCMP_256 = 10;
450 
451 
452     /**
453      * The detected signal level in dBm, also known as the RSSI.
454      *
455      * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
456      * an absolute signal level which can be displayed to a user.
457      */
458     public int level;
459 
460     /**
461      * The center frequency of the primary 20 MHz frequency (in MHz) of the channel over which the
462      * client is communicating with the access point.
463      */
464     public int frequency;
465 
466    /**
467     * AP Channel bandwidth is 20 MHZ
468     */
469     public static final int CHANNEL_WIDTH_20MHZ = 0;
470    /**
471     * AP Channel bandwidth is 40 MHZ
472     */
473     public static final int CHANNEL_WIDTH_40MHZ = 1;
474    /**
475     * AP Channel bandwidth is 80 MHZ
476     */
477     public static final int CHANNEL_WIDTH_80MHZ = 2;
478    /**
479     * AP Channel bandwidth is 160 MHZ
480     */
481     public static final int CHANNEL_WIDTH_160MHZ = 3;
482    /**
483     * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ
484     */
485     public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4;
486    /**
487     * AP Channel bandwidth is 320 MHZ
488     */
489     public static final int CHANNEL_WIDTH_320MHZ = 5;
490 
491     /**
492      * Preamble type: Legacy.
493      */
494     public static final int PREAMBLE_LEGACY = 0;
495     /**
496      * Preamble type: HT.
497      */
498     public static final int PREAMBLE_HT = 1;
499     /**
500      * Preamble type: VHT.
501      */
502     public static final int PREAMBLE_VHT = 2;
503     /**
504      * Preamble type: HE.
505      */
506     public static final int PREAMBLE_HE = 3;
507 
508     /**
509      * Preamble type: EHT.
510      */
511     public static final int PREAMBLE_EHT = 4;
512 
513     /**
514      * Wi-Fi unknown standard
515      */
516     public static final int WIFI_STANDARD_UNKNOWN = 0;
517 
518     /**
519      * Wi-Fi 802.11a/b/g
520      */
521     public static final int WIFI_STANDARD_LEGACY = 1;
522 
523     /**
524      * Wi-Fi 802.11n
525      */
526     public static final int WIFI_STANDARD_11N = 4;
527 
528     /**
529      * Wi-Fi 802.11ac
530      */
531     public static final int WIFI_STANDARD_11AC = 5;
532 
533     /**
534      * Wi-Fi 802.11ax
535      */
536     public static final int WIFI_STANDARD_11AX = 6;
537 
538     /**
539      * Wi-Fi 802.11ad
540      */
541     public static final int WIFI_STANDARD_11AD = 7;
542 
543     /**
544      * Wi-Fi 802.11be
545      */
546     public static final int WIFI_STANDARD_11BE = 8;
547 
548     /**
549      * Wi-Fi 2.4 GHz band.
550      */
551     public static final int WIFI_BAND_24_GHZ = WifiScanner.WIFI_BAND_24_GHZ;
552 
553     /**
554      * Wi-Fi 5 GHz band.
555      */
556     public static final int WIFI_BAND_5_GHZ = WifiScanner.WIFI_BAND_5_GHZ;
557 
558     /**
559      * Wi-Fi 6 GHz band.
560      */
561     public static final int WIFI_BAND_6_GHZ = WifiScanner.WIFI_BAND_6_GHZ;
562 
563     /**
564      * Wi-Fi 60 GHz band.
565      */
566     public static final int WIFI_BAND_60_GHZ = WifiScanner.WIFI_BAND_60_GHZ;
567 
568     /**
569      * Constant used for dual 5GHz multi-internet use-case only. Not to be used for regular scan
570      * result reporting.
571      * @hide
572      */
573     public static final int WIFI_BAND_5_GHZ_LOW = WifiScanner.WIFI_BAND_5_GHZ_LOW;
574 
575     /**
576      * Constant used for dual 5GHz multi-internet use-case only. Not to be used for regular scan
577      * result reporting.
578      * @hide
579      */
580     public static final int WIFI_BAND_5_GHZ_HIGH = WifiScanner.WIFI_BAND_5_GHZ_HIGH;
581 
582     /**
583      * @hide
584      */
585     @Retention(RetentionPolicy.SOURCE)
586     @IntDef(prefix = {"WIFI_BAND_"}, value = {
587             UNSPECIFIED,
588             WIFI_BAND_24_GHZ,
589             WIFI_BAND_5_GHZ,
590             WIFI_BAND_6_GHZ,
591             WIFI_BAND_60_GHZ})
592     public @interface WifiBand {};
593 
594     /**
595      * AP wifi standard.
596      */
597     private @WifiStandard int mWifiStandard = WIFI_STANDARD_UNKNOWN;
598 
599     /**
600      * return the AP wifi standard.
601      */
getWifiStandard()602     public @WifiStandard int getWifiStandard() {
603         return mWifiStandard;
604     }
605 
606     /**
607      * sets the AP wifi standard.
608      * @hide
609      */
setWifiStandard(@ifiStandard int standard)610     public void setWifiStandard(@WifiStandard int standard) {
611         mWifiStandard = standard;
612     }
613 
614     /**
615      * Convert Wi-Fi standard to string
616      * @hide
617      */
wifiStandardToString(@ifiStandard int standard)618     public static @Nullable String wifiStandardToString(@WifiStandard int standard) {
619         switch(standard) {
620             case WIFI_STANDARD_LEGACY:
621                 return "legacy";
622             case WIFI_STANDARD_11N:
623                 return "11n";
624             case WIFI_STANDARD_11AC:
625                 return "11ac";
626             case WIFI_STANDARD_11AX:
627                 return "11ax";
628             case WIFI_STANDARD_11AD:
629                 return "11ad";
630             case WIFI_STANDARD_11BE:
631                 return "11be";
632             case WIFI_STANDARD_UNKNOWN:
633                 return "unknown";
634         }
635         return null;
636     }
637 
638     /**
639      * AP Channel bandwidth; one of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
640      * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ}, {@link #CHANNEL_WIDTH_320MHZ},
641      * or {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}, or {@link #CHANNEL_WIDTH_320MHZ}
642      */
643     public @ChannelWidth int channelWidth;
644 
645     /**
646      * Not used if the AP bandwidth is 20 MHz
647      * If the AP use 40, 80, 160 or 320MHz, this is the center frequency (in MHz)
648      * if the AP use 80 + 80 MHz, this is the center frequency of the first segment (in MHz)
649      */
650     public int centerFreq0;
651 
652     /**
653      * Only used if the AP bandwidth is 80 + 80 MHz
654      * if the AP use 80 + 80 MHz, this is the center frequency of the second segment (in MHz)
655      */
656     public int centerFreq1;
657 
658     /**
659      * @deprecated use is80211mcResponder() instead
660      * @hide
661      */
662     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
663     public boolean is80211McRTTResponder;
664 
665     /**
666      * timestamp in microseconds (since boot) when
667      * this result was last seen.
668      */
669     public long timestamp;
670 
671     /**
672      * Timestamp representing date when this result was last seen, in milliseconds from 1970
673      * {@hide}
674      */
675     @UnsupportedAppUsage
676     public long seen;
677 
678     /**
679      * On devices with multiple hardware radio chains, this class provides metadata about
680      * each radio chain that was used to receive this scan result (probe response or beacon).
681      * {@hide}
682      */
683     public static class RadioChainInfo {
684         /** Vendor defined id for a radio chain. */
685         public int id;
686         /** Detected signal level in dBm (also known as the RSSI) on this radio chain. */
687         public int level;
688 
689         @Override
toString()690         public String toString() {
691             return "RadioChainInfo: id=" + id + ", level=" + level;
692         }
693 
694         @Override
equals(Object otherObj)695         public boolean equals(Object otherObj) {
696             if (this == otherObj) {
697                 return true;
698             }
699             if (!(otherObj instanceof RadioChainInfo)) {
700                 return false;
701             }
702             RadioChainInfo other = (RadioChainInfo) otherObj;
703             return id == other.id && level == other.level;
704         }
705 
706         @Override
hashCode()707         public int hashCode() {
708             return Objects.hash(id, level);
709         }
710     };
711 
712     /**
713      * Information about the list of the radio chains used to receive this scan result
714      * (probe response or beacon).
715      *
716      * For Example: On devices with 2 hardware radio chains, this list could hold 1 or 2
717      * entries based on whether this scan result was received using one or both the chains.
718      * {@hide}
719      */
720     public RadioChainInfo[] radioChainInfos;
721 
722     /**
723      * Status indicating the scan result does not correspond to a user's saved configuration
724      * @hide
725      * @removed
726      */
727     @SystemApi
728     public boolean untrusted;
729 
730     /**
731      * Number of time autojoin used it
732      * @hide
733      */
734     @UnsupportedAppUsage
735     public int numUsage;
736 
737     /**
738      * The approximate distance to the AP in centimeter, if available.  Else
739      * {@link #UNSPECIFIED}.
740      * {@hide}
741      */
742     @UnsupportedAppUsage
743     public int distanceCm;
744 
745     /**
746      * The standard deviation of the distance to the access point, if available.
747      * Else {@link #UNSPECIFIED}.
748      * {@hide}
749      */
750     @UnsupportedAppUsage
751     public int distanceSdCm;
752 
753     /** {@hide} */
754     public static final long FLAG_PASSPOINT_NETWORK               = 0x0000000000000001;
755 
756     /** {@hide} */
757     public static final long FLAG_80211mc_RESPONDER               = 0x0000000000000002;
758 
759     /** @hide */
760     public static final long FLAG_80211az_NTB_RESPONDER           = 0x0000000000000004;
761 
762     /** @hide */
763     public static final long FLAG_TWT_RESPONDER                    = 0x0000000000000008;
764 
765     /** @hide */
766     public static final long FLAG_SECURE_HE_LTF_SUPPORTED           = 0x0000000000000010;
767 
768     /** @hide */
769     public static final long FLAG_RANGING_FRAME_PROTECTION_REQUIRED = 0x0000000000000020;
770 
771     /*
772      * These flags are specific to the ScanResult class, and are not related to the |flags|
773      * field of the per-BSS scan results from WPA supplicant.
774      */
775     /**
776      * Defines flags; such as {@link #FLAG_PASSPOINT_NETWORK}.
777      * {@hide}
778      */
779     @UnsupportedAppUsage
780     public long flags;
781 
782     /**
783      * sets a flag in {@link #flags} field
784      * @param flag flag to set
785      * @hide
786      */
setFlag(long flag)787     public void setFlag(long flag) {
788         flags |= flag;
789     }
790 
791     /**
792      * clears a flag in {@link #flags} field
793      * @param flag flag to set
794      * @hide
795      */
clearFlag(long flag)796     public void clearFlag(long flag) {
797         flags &= ~flag;
798     }
799 
is80211mcResponder()800     public boolean is80211mcResponder() {
801         return (flags & FLAG_80211mc_RESPONDER) != 0;
802     }
803 
804     /**
805      * @return whether AP is a IEEE802.11az Non-Trigger based Ranging Responder.
806      */
807     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
is80211azNtbResponder()808     public boolean is80211azNtbResponder() {
809         return (flags & FLAG_80211az_NTB_RESPONDER) != 0;
810     }
811 
isPasspointNetwork()812     public boolean isPasspointNetwork() {
813         return (flags & FLAG_PASSPOINT_NETWORK) != 0;
814     }
815 
816     /**
817      * @return whether AP is Target Wake Time (TWT) Responder.
818      */
819     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
isTwtResponder()820     public boolean isTwtResponder() {
821         return (flags & FLAG_TWT_RESPONDER) != 0;
822     }
823 
824     /**
825      * Returns whether the AP supports secure HE-LTF for ranging measurement.
826      *
827      * Secure HE-LTF (High Efficiency Long Training Field), is a security enhancement for the HE
828      * PHY (High Efficiency Physical Layer) that aims to protect ranging measurements by using
829      * randomized HE-LTF sequences. This prevents attackers from exploiting predictable HE-LTF
830      * patterns. IEEE 802.11az adds secure HE-LTF support in Extended RSN capabilities.
831      */
832     @FlaggedApi(Flags.FLAG_SECURE_RANGING)
isSecureHeLtfSupported()833     public boolean isSecureHeLtfSupported() {
834         return (flags & FLAG_SECURE_HE_LTF_SUPPORTED) != 0;
835     }
836 
837     /**
838      * Returns whether the AP requires frame protection for ranging measurement.
839      *
840      * Ranging frame protection in IEEE 802.11az, also known as URNM-MFPR (Unassociated Range
841      * Negotiation and Measurement Management Frame Protection Required), is a security policy
842      * that dictates whether ranging frames are required to be protected even without a formal
843      * association between the Initiating STA (ISTA) and Responding STA (RSTA)
844      */
845     @FlaggedApi(Flags.FLAG_SECURE_RANGING)
isRangingFrameProtectionRequired()846     public boolean isRangingFrameProtectionRequired() {
847         return (flags & FLAG_RANGING_FRAME_PROTECTION_REQUIRED) != 0;
848     }
849 
850 
851     /**
852      * Indicates venue name (such as 'San Francisco Airport') published by access point; only
853      * available on Passpoint network and if published by access point.
854      * @deprecated - This information is not provided
855      */
856     @Deprecated
857     public CharSequence venueName;
858 
859     /**
860      * Indicates Passpoint operator name published by access point.
861      * @deprecated - Use {@link WifiInfo#getPasspointProviderFriendlyName()}
862      */
863     @Deprecated
864     public CharSequence operatorFriendlyName;
865 
866     /**
867      * The unspecified value.
868      */
869     public final static int UNSPECIFIED = -1;
870 
871     /**
872      * 2.4 GHz band first channel number
873      * @hide
874      */
875     public static final int BAND_24_GHZ_FIRST_CH_NUM = 1;
876     /**
877      * 2.4 GHz band last channel number
878      * @hide
879      */
880     public static final int BAND_24_GHZ_LAST_CH_NUM = 14;
881     /**
882      * 2.4 GHz band frequency of first channel in MHz
883      * @hide
884      */
885     public static final int BAND_24_GHZ_START_FREQ_MHZ = 2412;
886     /**
887      * 2.4 GHz band frequency of last channel in MHz
888      * @hide
889      */
890     public static final int BAND_24_GHZ_END_FREQ_MHZ = 2484;
891 
892     /**
893      * 5 GHz band first channel number
894      * @hide
895      */
896     public static final int BAND_5_GHZ_FIRST_CH_NUM = 32;
897     /**
898      * 5 GHz band last channel number
899      * @hide
900      */
901     public static final int BAND_5_GHZ_LAST_CH_NUM = 177;
902     /**
903      * 5 GHz band frequency of first channel in MHz
904      * @hide
905      */
906     public static final int BAND_5_GHZ_START_FREQ_MHZ = 5160;
907     /**
908      * 5 GHz band frequency of last channel in MHz
909      * @hide
910      */
911     public static final int BAND_5_GHZ_END_FREQ_MHZ = 5885;
912 
913     /**
914      * 6 GHz band first channel number
915      * @hide
916      */
917     public static final int BAND_6_GHZ_FIRST_CH_NUM = 1;
918     /**
919      * 6 GHz band last channel number
920      * @hide
921      */
922     public static final int BAND_6_GHZ_LAST_CH_NUM = 233;
923     /**
924      * 6 GHz band frequency of first channel in MHz
925      * @hide
926      */
927     public static final int BAND_6_GHZ_START_FREQ_MHZ = 5955;
928     /**
929      * 6 GHz band frequency of last channel in MHz
930      * @hide
931      */
932     public static final int BAND_6_GHZ_END_FREQ_MHZ = 7115;
933     /**
934      * The center frequency of the first 6Ghz preferred scanning channel, as defined by
935      * IEEE802.11ax draft 7.0 section 26.17.2.3.3.
936      * @hide
937      */
938     public static final int BAND_6_GHZ_PSC_START_MHZ = 5975;
939     /**
940      * The number of MHz to increment in order to get the next 6Ghz preferred scanning channel
941      * as defined by IEEE802.11ax draft 7.0 section 26.17.2.3.3.
942      * @hide
943      */
944     public static final int BAND_6_GHZ_PSC_STEP_SIZE_MHZ = 80;
945 
946     /**
947      * 6 GHz band operating class 136 channel 2 center frequency in MHz
948      * @hide
949      */
950     public static final int BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ = 5935;
951 
952     /**
953      * 60 GHz band first channel number
954      * @hide
955      */
956     public static final int BAND_60_GHZ_FIRST_CH_NUM = 1;
957     /**
958      * 60 GHz band last channel number
959      * @hide
960      */
961     public static final int BAND_60_GHZ_LAST_CH_NUM = 6;
962     /**
963      * 60 GHz band frequency of first channel in MHz
964      * @hide
965      */
966     public static final int BAND_60_GHZ_START_FREQ_MHZ = 58320;
967     /**
968      * 60 GHz band frequency of last channel in MHz
969      * @hide
970      */
971     public static final int BAND_60_GHZ_END_FREQ_MHZ = 70200;
972     /**
973      * The highest frequency in 5GHz low
974      * @hide
975      */
976     public static final int BAND_5_GHZ_LOW_HIGHEST_FREQ_MHZ = 5320;
977     /**
978      * The lowest frequency in 5GHz high
979      * @hide
980      */
981     public static final int BAND_5_GHZ_HIGH_LOWEST_FREQ_MHZ = 5500;
982 
983     /**
984      * Utility function to check if a frequency within 2.4 GHz band
985      * @param freqMhz frequency in MHz
986      * @return true if within 2.4GHz, false otherwise
987      *
988      * @hide
989      */
990     @Keep
is24GHz(int freqMhz)991     public static boolean is24GHz(int freqMhz) {
992         return freqMhz >= BAND_24_GHZ_START_FREQ_MHZ && freqMhz <= BAND_24_GHZ_END_FREQ_MHZ;
993     }
994 
995     /**
996      * Utility function to check if a frequency within 5 GHz band
997      * @param freqMhz frequency in MHz
998      * @return true if within 5GHz, false otherwise
999      *
1000      * @hide
1001      */
1002     @Keep
is5GHz(int freqMhz)1003     public static boolean is5GHz(int freqMhz) {
1004         return freqMhz >=  BAND_5_GHZ_START_FREQ_MHZ && freqMhz <= BAND_5_GHZ_END_FREQ_MHZ;
1005     }
1006 
1007     /**
1008      * Utility function to check if a frequency within 6 GHz band
1009      * @param freqMhz
1010      * @return true if within 6GHz, false otherwise
1011      *
1012      * @hide
1013      */
1014     @Keep
is6GHz(int freqMhz)1015     public static boolean is6GHz(int freqMhz) {
1016         if (freqMhz == BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ) {
1017             return true;
1018         }
1019         return (freqMhz >= BAND_6_GHZ_START_FREQ_MHZ && freqMhz <= BAND_6_GHZ_END_FREQ_MHZ);
1020     }
1021 
1022     /**
1023      * Utility function to check if a frequency is 6Ghz PSC channel.
1024      * @param freqMhz
1025      * @return true if the frequency is 6GHz PSC, false otherwise
1026      *
1027      * @hide
1028      */
is6GHzPsc(int freqMhz)1029     public static boolean is6GHzPsc(int freqMhz) {
1030         if (!ScanResult.is6GHz(freqMhz)) {
1031             return false;
1032         }
1033         return (freqMhz - BAND_6_GHZ_PSC_START_MHZ) % BAND_6_GHZ_PSC_STEP_SIZE_MHZ == 0;
1034     }
1035 
1036     /**
1037      * Utility function to check if a frequency within 60 GHz band
1038      * @param freqMhz
1039      * @return true if within 60GHz, false otherwise
1040      *
1041      * @hide
1042      */
is60GHz(int freqMhz)1043     public static boolean is60GHz(int freqMhz) {
1044         return freqMhz >= BAND_60_GHZ_START_FREQ_MHZ && freqMhz <= BAND_60_GHZ_END_FREQ_MHZ;
1045     }
1046 
1047     /**
1048      * Utility function to check whether 2 frequencies are valid for multi-internet connection
1049      * when dual-5GHz is supported.
1050      *
1051      * The allowed combinations are:
1052      * - 2.4GHz + Any 5GHz
1053      * - 2.4GHz + 6Ghz
1054      * - 5GHz low + 5GHz high
1055      * - 5GHz low + 6GHz
1056      * @hide
1057      */
isValidCombinedBandForDual5GHz(int freqMhz1, int freqMhz2)1058     public static boolean isValidCombinedBandForDual5GHz(int freqMhz1, int freqMhz2) {
1059         int band1 = toBand(freqMhz1);
1060         int band2 = toBand(freqMhz2);
1061         if (band1 == WIFI_BAND_24_GHZ || band2 == WIFI_BAND_24_GHZ) {
1062             return band1 != band2;
1063         }
1064 
1065         // 5GHz Low : b1 36-48 b2 52-64(5320)
1066         // 5GHz High : b3 100(5500)-144 b4 149-165
1067         if ((freqMhz1 <= BAND_5_GHZ_LOW_HIGHEST_FREQ_MHZ
1068                 && freqMhz2 >= BAND_5_GHZ_HIGH_LOWEST_FREQ_MHZ)
1069                     || (freqMhz2 <= BAND_5_GHZ_LOW_HIGHEST_FREQ_MHZ
1070                         && freqMhz1 >= BAND_5_GHZ_HIGH_LOWEST_FREQ_MHZ)) {
1071             return true;
1072         }
1073         return false;
1074     }
1075 
1076     /**
1077      * Utility function to convert Wi-Fi channel number to frequency in MHz.
1078      *
1079      * Reference the Wi-Fi channel numbering and the channelization in IEEE 802.11-2016
1080      * specifications, section 17.3.8.4.2, 17.3.8.4.3 and Table 15-6.
1081      *
1082      * See also {@link #convertFrequencyMhzToChannelIfSupported(int)}.
1083      *
1084      * @param channel number to convert.
1085      * @param band of channel to convert. One of the following bands:
1086      *        {@link #WIFI_BAND_24_GHZ},  {@link #WIFI_BAND_5_GHZ},
1087      *        {@link #WIFI_BAND_6_GHZ},  {@link #WIFI_BAND_60_GHZ}.
1088      * @return center frequency in Mhz of the channel, {@link #UNSPECIFIED} if no match
1089      */
convertChannelToFrequencyMhzIfSupported(int channel, @WifiBand int band)1090     public static int convertChannelToFrequencyMhzIfSupported(int channel, @WifiBand int band) {
1091         if (band == WIFI_BAND_24_GHZ) {
1092             // Special case
1093             if (channel == 14) {
1094                 return 2484;
1095             } else if (channel >= BAND_24_GHZ_FIRST_CH_NUM && channel <= BAND_24_GHZ_LAST_CH_NUM) {
1096                 return ((channel - BAND_24_GHZ_FIRST_CH_NUM) * 5) + BAND_24_GHZ_START_FREQ_MHZ;
1097             } else {
1098                 return UNSPECIFIED;
1099             }
1100         }
1101         if (band == WIFI_BAND_5_GHZ) {
1102             if (channel >= BAND_5_GHZ_FIRST_CH_NUM && channel <= BAND_5_GHZ_LAST_CH_NUM) {
1103                 return ((channel - BAND_5_GHZ_FIRST_CH_NUM) * 5) + BAND_5_GHZ_START_FREQ_MHZ;
1104             } else {
1105                 return UNSPECIFIED;
1106             }
1107         }
1108         if (band == WIFI_BAND_6_GHZ) {
1109             if (channel >= BAND_6_GHZ_FIRST_CH_NUM && channel <= BAND_6_GHZ_LAST_CH_NUM) {
1110                 if (channel == 2) {
1111                     return BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ;
1112                 }
1113                 return ((channel - BAND_6_GHZ_FIRST_CH_NUM) * 5) + BAND_6_GHZ_START_FREQ_MHZ;
1114             } else {
1115                 return UNSPECIFIED;
1116             }
1117         }
1118         if (band == WIFI_BAND_60_GHZ) {
1119             if (channel >= BAND_60_GHZ_FIRST_CH_NUM && channel <= BAND_60_GHZ_LAST_CH_NUM) {
1120                 return ((channel - BAND_60_GHZ_FIRST_CH_NUM) * 2160) + BAND_60_GHZ_START_FREQ_MHZ;
1121             } else {
1122                 return UNSPECIFIED;
1123             }
1124         }
1125         return UNSPECIFIED;
1126     }
1127 
1128     /**
1129      * Utility function to convert Operating Class into a band
1130      *
1131      * Use 802.11 Specification Table E-4: Global Operating Classes for decoding
1132      *
1133      * @param opClass operating class
1134      * @param channel number
1135      *
1136      * @return one of {@link WifiScanner.WIFI_BAND_24_GHZ}, {@link WifiScanner.WIFI_BAND_5_GHZ}, or
1137      *         {@link WifiScanner.WIFI_BAND_6_GHZ} for a valid opClass, channel pair, otherwise
1138      *         {@link WifiScanner.WIFI_BAND_UNSPECIFIED} is returned.
1139      *
1140      * @hide
1141      */
getBandFromOpClass(int opClass, int channel)1142     public static int getBandFromOpClass(int opClass, int channel) {
1143         if (opClass >= 81 && opClass <= 84) {
1144             if (channel >= BAND_24_GHZ_FIRST_CH_NUM && channel <= BAND_24_GHZ_LAST_CH_NUM) {
1145                 return WifiScanner.WIFI_BAND_24_GHZ;
1146             }
1147         } else if (opClass >= 115 && opClass <= 130) {
1148             if (channel >= BAND_5_GHZ_FIRST_CH_NUM && channel <= BAND_5_GHZ_LAST_CH_NUM) {
1149                 return WifiScanner.WIFI_BAND_5_GHZ;
1150             }
1151         } else if (opClass >= 131 && opClass <= 137) {
1152             if (channel >= BAND_6_GHZ_FIRST_CH_NUM && channel <= BAND_6_GHZ_LAST_CH_NUM) {
1153                 return WifiScanner.WIFI_BAND_6_GHZ;
1154             }
1155         }
1156 
1157         // If none of the above combinations, then return as invalid band
1158         return WifiScanner.WIFI_BAND_UNSPECIFIED;
1159     }
1160 
1161     /**
1162      * Utility function to convert frequency in MHz to channel number.
1163      *
1164      * See also {@link #convertChannelToFrequencyMhzIfSupported(int, int)}.
1165      *
1166      * @param freqMhz frequency in MHz
1167      * @return channel number associated with given frequency, {@link #UNSPECIFIED} if no match
1168      */
convertFrequencyMhzToChannelIfSupported(int freqMhz)1169     public static int convertFrequencyMhzToChannelIfSupported(int freqMhz) {
1170         // Special case
1171         if (freqMhz == 2484) {
1172             return 14;
1173         } else if (is24GHz(freqMhz)) {
1174             return (freqMhz - BAND_24_GHZ_START_FREQ_MHZ) / 5 + BAND_24_GHZ_FIRST_CH_NUM;
1175         } else if (is5GHz(freqMhz)) {
1176             return ((freqMhz - BAND_5_GHZ_START_FREQ_MHZ) / 5) + BAND_5_GHZ_FIRST_CH_NUM;
1177         } else if (is6GHz(freqMhz)) {
1178             if (freqMhz == BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ) {
1179                 return 2;
1180             }
1181             return ((freqMhz - BAND_6_GHZ_START_FREQ_MHZ) / 5) + BAND_6_GHZ_FIRST_CH_NUM;
1182         } else if (is60GHz(freqMhz)) {
1183             return ((freqMhz - BAND_60_GHZ_START_FREQ_MHZ) / 2160) + BAND_60_GHZ_FIRST_CH_NUM;
1184         }
1185 
1186         return UNSPECIFIED;
1187     }
1188 
1189     /**
1190      * Returns the band for the ScanResult according to its frequency.
1191      * @hide
1192      */
toBand(int frequency)1193     @WifiBand public static int toBand(int frequency) {
1194         if (ScanResult.is24GHz(frequency)) {
1195             return ScanResult.WIFI_BAND_24_GHZ;
1196         } else if (ScanResult.is5GHz(frequency)) {
1197             return ScanResult.WIFI_BAND_5_GHZ;
1198         } else if (ScanResult.is6GHz(frequency)) {
1199             return ScanResult.WIFI_BAND_6_GHZ;
1200         } else if (ScanResult.is60GHz(frequency)) {
1201             return ScanResult.WIFI_BAND_60_GHZ;
1202         }
1203         return ScanResult.UNSPECIFIED;
1204     }
1205 
1206     /**
1207      * Returns the band for the ScanResult according to its frequency.
1208      * @hide
1209      */
1210     @SystemApi
getBand()1211     @WifiBand public int getBand() {
1212         return ScanResult.toBand(this.frequency);
1213     }
1214 
1215     /**
1216      * @hide
1217      */
is24GHz()1218     public boolean is24GHz() {
1219         return ScanResult.is24GHz(frequency);
1220     }
1221 
1222     /**
1223      * @hide
1224      */
is5GHz()1225     public boolean is5GHz() {
1226         return ScanResult.is5GHz(frequency);
1227     }
1228 
1229     /**
1230      * @hide
1231      */
is6GHz()1232     public boolean is6GHz() {
1233         return ScanResult.is6GHz(frequency);
1234     }
1235 
1236     /**
1237      * @hide
1238      */
is6GhzPsc()1239     public boolean is6GhzPsc() {
1240         return ScanResult.is6GHzPsc(frequency);
1241     }
1242 
1243     /**
1244      * @hide
1245      */
is60GHz()1246     public boolean is60GHz() {
1247         return ScanResult.is60GHz(frequency);
1248     }
1249 
1250     /**
1251      *  @hide
1252      * anqp lines from supplicant BSS response
1253      */
1254     @UnsupportedAppUsage
1255     public List<String> anqpLines;
1256 
1257     /**
1258      * information elements from beacon.
1259      */
1260     public static class InformationElement implements Parcelable {
1261         /** @hide */
1262         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1263         public static final int EID_SSID = 0;
1264         /** @hide */
1265         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1266         public static final int EID_SUPPORTED_RATES = 1;
1267         /** @hide */
1268         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1269         public static final int EID_TIM = 5;
1270         /** @hide */
1271         public static final int EID_COUNTRY = 7;
1272         /** @hide */
1273         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1274         public static final int EID_BSS_LOAD = 11;
1275         /** @hide */
1276         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1277         public static final int EID_ERP = 42;
1278         /** @hide */
1279         public static final int EID_HT_CAPABILITIES = 45;
1280         /** @hide */
1281         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1282         public static final int EID_RSN = 48;
1283         /** @hide */
1284         public static final int EID_RSN_EXTENSION = 244;
1285         /** @hide */
1286         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1287         public static final int EID_EXTENDED_SUPPORTED_RATES = 50;
1288         /** @hide */
1289         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1290         public static final int EID_HT_OPERATION = 61;
1291         /** @hide */
1292         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1293         public static final int EID_INTERWORKING = 107;
1294         /** @hide */
1295         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1296         public static final int EID_ROAMING_CONSORTIUM = 111;
1297         /** @hide */
1298         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1299         public static final int EID_EXTENDED_CAPS = 127;
1300         /** @hide */
1301         public static final int EID_VHT_CAPABILITIES = 191;
1302         /** @hide */
1303         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1304         public static final int EID_VHT_OPERATION = 192;
1305         /** @hide */
1306         public static final int EID_RNR = 201;
1307         /** @hide */
1308         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1309         public static final int EID_VSA = 221;
1310         /** @hide */
1311         public static final int EID_EXTENSION_PRESENT = 255;
1312 
1313         // Extension IDs
1314         /** @hide */
1315         public static final int EID_EXT_HE_CAPABILITIES = 35;
1316         /** @hide */
1317         public static final int EID_EXT_HE_OPERATION = 36;
1318         /**
1319          * EHT Operation IE extension id: see IEEE 802.11be Specification section 9.4.2.1
1320          *
1321          * @hide
1322          */
1323         public static final int EID_EXT_EHT_OPERATION = 106;
1324         /**
1325          * Multi-Link IE extension id: see IEEE 802.11be Specification section 9.4.2.1
1326          *
1327          * @hide
1328          */
1329         public static final int EID_EXT_MULTI_LINK = 107;
1330         /**
1331          * Multi-Link IE Fragment sub element ID: see IEEE 802.11be Specification section 9.4.2.312
1332          * Multi-Link element.
1333          *
1334          * @hide
1335          */
1336         public static final int EID_FRAGMENT_SUB_ELEMENT_MULTI_LINK = 254;
1337 
1338         /**
1339          * EHT Capabilities IE extension id: see IEEE 802.11be Specification section 9.4.2.1
1340          *
1341          * @hide
1342          */
1343         public static final int EID_EXT_EHT_CAPABILITIES = 108;
1344 
1345         /** @hide */
1346         @UnsupportedAppUsage
1347         public int id;
1348         /** @hide */
1349         public int idExt;
1350 
1351         /** @hide */
1352         @UnsupportedAppUsage
1353         public byte[] bytes;
1354 
1355         /** @hide */
InformationElement()1356         public InformationElement() {
1357         }
1358 
1359         /**
1360          * Constructs InformationElements from beacon.
1361          *
1362          * @param id element id
1363          * @param idExt element id extension
1364          * @param bytes the body of the information element, may contain multiple elements
1365          */
InformationElement(int id, int idExt, @NonNull byte[] bytes)1366         public InformationElement(int id, int idExt, @NonNull byte[] bytes) {
1367             this.id = id;
1368             this.idExt = idExt;
1369             this.bytes = bytes.clone();
1370         }
1371 
InformationElement(@onNull InformationElement rhs)1372         public InformationElement(@NonNull InformationElement rhs) {
1373             this.id = rhs.id;
1374             this.idExt = rhs.idExt;
1375             this.bytes = rhs.bytes.clone();
1376         }
1377 
1378         /**
1379          * The element ID of the information element. Defined in the IEEE 802.11-2016 spec
1380          * Table 9-77.
1381          */
getId()1382         public int getId() {
1383             return id;
1384         }
1385 
1386         /**
1387          * The element ID Extension of the information element. Defined in the IEEE 802.11-2016 spec
1388          * Table 9-77.
1389          */
getIdExt()1390         public int getIdExt() {
1391             return idExt;
1392         }
1393 
1394         /**
1395          * Get the specific content of the information element.
1396          */
1397         @NonNull
getBytes()1398         public ByteBuffer getBytes() {
1399             return ByteBuffer.wrap(bytes).asReadOnlyBuffer();
1400         }
1401 
1402         /** Implement the Parcelable interface {@hide} */
describeContents()1403         public int describeContents() {
1404             return 0;
1405         }
1406 
1407         /** Implement the Parcelable interface {@hide} */
writeToParcel(Parcel dest, int flags)1408         public void writeToParcel(Parcel dest, int flags) {
1409             dest.writeInt(id);
1410             dest.writeInt(idExt);
1411             dest.writeByteArray(bytes);
1412         }
1413 
1414         /** Implement the Parcelable interface */
1415         public static final @NonNull Creator<InformationElement> CREATOR =
1416                 new Creator<InformationElement>() {
1417                     public InformationElement createFromParcel(Parcel in) {
1418                         InformationElement informationElement = new InformationElement();
1419                         informationElement.id = in.readInt();
1420                         informationElement.idExt = in.readInt();
1421                         informationElement.bytes = in.createByteArray();
1422                         return informationElement;
1423                     }
1424 
1425                     public InformationElement[] newArray(int size) {
1426                         return new InformationElement[size];
1427                     }
1428                 };
1429 
1430         @Override
equals(Object that)1431         public boolean equals(Object that) {
1432             if (this == that) return true;
1433 
1434             // Potential API behavior change, so don't change behavior on older devices.
1435             if (!SdkLevel.isAtLeastS()) return false;
1436 
1437             if (!(that instanceof InformationElement)) return false;
1438 
1439             InformationElement thatIE = (InformationElement) that;
1440             return id == thatIE.id
1441                     && idExt == thatIE.idExt
1442                     && Arrays.equals(bytes, thatIE.bytes);
1443         }
1444 
1445         @Override
hashCode()1446         public int hashCode() {
1447             // Potential API behavior change, so don't change behavior on older devices.
1448             if (!SdkLevel.isAtLeastS()) return System.identityHashCode(this);
1449 
1450             return Objects.hash(id, idExt, Arrays.hashCode(bytes));
1451         }
1452     }
1453 
1454     /**
1455      * information elements found in the beacon.
1456      * @hide
1457      */
1458     @UnsupportedAppUsage
1459     public InformationElement[] informationElements;
1460     /**
1461      * Get all information elements found in the beacon.
1462      */
1463     @NonNull
getInformationElements()1464     public List<InformationElement> getInformationElements() {
1465         return Collections.unmodifiableList(Arrays.asList(informationElements));
1466     }
1467 
1468     /**
1469      * Get all the security types supported by this ScanResult.
1470      * @return array of {@code WifiInfo#SECURITY_TYPE_*}.
1471      */
1472     @NonNull
getSecurityTypes()1473     public @WifiAnnotations.SecurityType int[] getSecurityTypes() {
1474         List<SecurityParams> params = ScanResultUtil.generateSecurityParamsListFromScanResult(this);
1475         int[] securityTypes = new int[params.size()];
1476         for (int i = 0; i < securityTypes.length; i++) {
1477             securityTypes[i] = WifiInfo.convertWifiConfigurationSecurityType(
1478                     params.get(i).getSecurityType());
1479         }
1480         return securityTypes;
1481     }
1482 
1483     /** ANQP response elements.
1484      * @hide
1485      */
1486     public AnqpInformationElement[] anqpElements;
1487 
1488     /**
1489      * Returns whether a WifiSsid represents a "hidden" SSID of all zero values.
1490      */
isHiddenSsid(@onNull WifiSsid wifiSsid)1491     private boolean isHiddenSsid(@NonNull WifiSsid wifiSsid) {
1492         for (byte b : wifiSsid.getBytes()) {
1493             if (b != 0) {
1494                 return false;
1495             }
1496         }
1497         return true;
1498     }
1499 
1500     /**
1501      * Builder class used to construct {@link ScanResult} objects.
1502      *
1503      * @hide
1504      */
1505     public static final class Builder {
1506         private WifiSsid mWifiSsid;
1507         private String mBssid;
1508         private long mHessid = 0;
1509         private int mAnqpDomainId = 0;
1510         private byte[] mOsuProviders = null;
1511         private String mCaps = null;
1512         private int mRssi = UNSPECIFIED;
1513         private int mFrequency = UNSPECIFIED;
1514         private long mTsf = 0;
1515         private int mDistanceCm = UNSPECIFIED;
1516         private int mDistanceSdCm = UNSPECIFIED;
1517         private @ChannelWidth int mChannelWidth = ScanResult.CHANNEL_WIDTH_20MHZ;
1518         private int mCenterFreq0 = UNSPECIFIED;
1519         private int mCenterFreq1 = UNSPECIFIED;
1520         private boolean mIs80211McRTTResponder = false;
1521         private boolean mIs80211azNtbRTTResponder = false;
1522         private boolean mIsTwtResponder = false;
1523         private boolean mIsSecureHeLtfSupported = false;
1524         private boolean mIsRangingFrameProtectionRequired = false;
1525 
1526         /** @hide */
1527         @NonNull
setHessid(long hessid)1528         public Builder setHessid(long hessid) {
1529             mHessid = hessid;
1530             return this;
1531         }
1532 
1533         /** @hide */
1534         @NonNull
setOsuProviders(@ullable byte[] osuProviders)1535         public Builder setOsuProviders(@Nullable byte[] osuProviders) {
1536             mOsuProviders = osuProviders;
1537             return this;
1538         }
1539 
1540         /** @hide */
1541         @NonNull
setAnqpDomainId(int anqpDomainId)1542         public Builder setAnqpDomainId(int anqpDomainId) {
1543             mAnqpDomainId = anqpDomainId;
1544             return this;
1545         }
1546 
1547         /** @hide */
1548         @NonNull
setCaps(@ullable String caps)1549         public Builder setCaps(@Nullable String caps) {
1550             mCaps = caps;
1551             return this;
1552         }
1553 
1554         /** @hide */
1555         @NonNull
setRssi(int rssi)1556         public Builder setRssi(int rssi) {
1557             mRssi = rssi;
1558             return this;
1559         }
1560 
1561         /** @hide */
1562         @NonNull
setFrequency(int frequency)1563         public Builder setFrequency(int frequency) {
1564             mFrequency = frequency;
1565             return this;
1566         }
1567 
1568         /** @hide */
1569         @NonNull
setTsf(long tsf)1570         public Builder setTsf(long tsf) {
1571             mTsf = tsf;
1572             return this;
1573         }
1574 
1575         /** @hide */
1576         @NonNull
setDistanceCm(int distanceCm)1577         public Builder setDistanceCm(int distanceCm) {
1578             mDistanceCm = distanceCm;
1579             return this;
1580         }
1581 
1582         /** @hide */
1583         @NonNull
setDistanceSdCm(int distanceSdCm)1584         public Builder setDistanceSdCm(int distanceSdCm) {
1585             mDistanceSdCm = distanceSdCm;
1586             return this;
1587         }
1588 
1589         /** @hide */
1590         @NonNull
setChannelWidth(@hannelWidth int channelWidth)1591         public Builder setChannelWidth(@ChannelWidth int channelWidth) {
1592             mChannelWidth = channelWidth;
1593             return this;
1594         }
1595 
1596         /** @hide */
1597         @NonNull
setCenterFreq0(int centerFreq0)1598         public Builder setCenterFreq0(int centerFreq0) {
1599             mCenterFreq0 = centerFreq0;
1600             return this;
1601         }
1602 
1603         /** @hide */
1604         @NonNull
setCenterFreq1(int centerFreq1)1605         public Builder setCenterFreq1(int centerFreq1) {
1606             mCenterFreq1 = centerFreq1;
1607             return this;
1608         }
1609 
1610         /** @hide */
1611         @NonNull
setIs80211McRTTResponder(boolean is80211McRTTResponder)1612         public Builder setIs80211McRTTResponder(boolean is80211McRTTResponder) {
1613             mIs80211McRTTResponder = is80211McRTTResponder;
1614             return this;
1615         }
1616 
1617         /** @hide */
1618         @NonNull
setIs80211azNtbRTTResponder(boolean is80211azNtbRTTResponder)1619         public Builder setIs80211azNtbRTTResponder(boolean is80211azNtbRTTResponder) {
1620             mIs80211azNtbRTTResponder = is80211azNtbRTTResponder;
1621             return this;
1622         }
1623 
1624         /** @hide */
1625         @NonNull
setIsTwtResponder(boolean isTwtResponder)1626         public Builder setIsTwtResponder(boolean isTwtResponder) {
1627             mIsTwtResponder = isTwtResponder;
1628             return this;
1629         }
1630 
1631         /** @hide */
Builder(WifiSsid wifiSsid, String bssid)1632         public Builder(WifiSsid wifiSsid, String bssid) {
1633             mWifiSsid = wifiSsid;
1634             mBssid = bssid;
1635         }
1636 
1637         /**
1638          * @hide
1639          *
1640          */
Builder()1641         public Builder() {
1642 
1643         }
1644 
1645         /**
1646          * @hide
1647          */
setWifiSsid(WifiSsid wifiSsid)1648         public Builder setWifiSsid(WifiSsid wifiSsid) {
1649             mWifiSsid = wifiSsid;
1650             return this;
1651         }
1652 
1653         /**
1654          * @hide
1655          */
setBssid(String bssid)1656         public Builder setBssid(String bssid) {
1657             mBssid = bssid;
1658             return this;
1659         }
1660 
1661         /**
1662          * @hide
1663          */
clear()1664         public void clear() {
1665             mWifiSsid = null;
1666             mBssid = null;
1667             mHessid = 0;
1668             mAnqpDomainId = 0;
1669             mOsuProviders = null;
1670             mCaps = null;
1671             mRssi = UNSPECIFIED;
1672             mFrequency = UNSPECIFIED;
1673             mTsf = 0;
1674             mDistanceCm = UNSPECIFIED;
1675             mDistanceSdCm = UNSPECIFIED;
1676             mChannelWidth = ScanResult.CHANNEL_WIDTH_20MHZ;
1677             mCenterFreq0 = UNSPECIFIED;
1678             mCenterFreq1 = UNSPECIFIED;
1679             mIs80211McRTTResponder = false;
1680             mIs80211azNtbRTTResponder = false;
1681             mIsTwtResponder = false;
1682         }
1683 
1684         /** @hide */
build()1685         public ScanResult build() {
1686             return new ScanResult(this);
1687         }
1688 
1689         /** @hide */
setSecureHeLtfSupported(boolean supported)1690         public Builder setSecureHeLtfSupported(boolean supported) {
1691             mIsSecureHeLtfSupported = supported;
1692             return this;
1693         }
1694 
1695         /** @hide */
setRangingFrameProtectionRequired(boolean required)1696         public Builder setRangingFrameProtectionRequired(boolean required) {
1697             mIsRangingFrameProtectionRequired = required;
1698             return this;
1699         }
1700     }
1701 
1702     /**
1703      * @hide
1704      */
ScanResult(Builder builder)1705     private ScanResult(Builder builder) {
1706         this.wifiSsid = builder.mWifiSsid;
1707         if (wifiSsid != null && isHiddenSsid(wifiSsid)) {
1708             // Retain the legacy behavior of setting SSID to "" if the SSID is all zero values.
1709             this.SSID = "";
1710         } else {
1711             final CharSequence utf8Ssid = (wifiSsid != null) ? wifiSsid.getUtf8Text() : null;
1712             this.SSID = (utf8Ssid != null) ? utf8Ssid.toString() : WifiManager.UNKNOWN_SSID;
1713         }
1714         this.BSSID = builder.mBssid;
1715         this.hessid = builder.mHessid;
1716         this.anqpDomainId = builder.mAnqpDomainId;
1717         if (builder.mOsuProviders != null) {
1718             this.anqpElements = new AnqpInformationElement[1];
1719             this.anqpElements[0] = new AnqpInformationElement(
1720                     AnqpInformationElement.HOTSPOT20_VENDOR_ID,
1721                     AnqpInformationElement.HS_OSU_PROVIDERS, builder.mOsuProviders);
1722         }
1723         this.capabilities = builder.mCaps;
1724         this.level = builder.mRssi;
1725         this.frequency = builder.mFrequency;
1726         this.timestamp = builder.mTsf;
1727         this.distanceCm = builder.mDistanceCm;
1728         this.distanceSdCm = builder.mDistanceSdCm;
1729         this.channelWidth = builder.mChannelWidth;
1730         this.centerFreq0 = builder.mCenterFreq0;
1731         this.centerFreq1 = builder.mCenterFreq1;
1732         this.flags = 0;
1733         this.flags |= (builder.mIs80211McRTTResponder) ? FLAG_80211mc_RESPONDER : 0;
1734         this.flags |= (builder.mIs80211azNtbRTTResponder) ? FLAG_80211az_NTB_RESPONDER : 0;
1735         this.flags |= (builder.mIsTwtResponder) ? FLAG_TWT_RESPONDER : 0;
1736         this.radioChainInfos = null;
1737         this.mApMldMacAddress = null;
1738         this.flags |= (builder.mIsSecureHeLtfSupported) ? FLAG_SECURE_HE_LTF_SUPPORTED : 0;
1739         this.flags |= (builder.mIsRangingFrameProtectionRequired)
1740                 ? FLAG_RANGING_FRAME_PROTECTION_REQUIRED : 0;
1741     }
1742 
1743     /**
1744      * @hide
1745      * @deprecated Use {@link ScanResult.Builder}
1746      */
ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId, byte[] osuProviders, String caps, int level, int frequency, long tsf)1747     public ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId,
1748             byte[] osuProviders, String caps, int level, int frequency, long tsf) {
1749         this.wifiSsid = wifiSsid;
1750         if (wifiSsid != null && isHiddenSsid(wifiSsid)) {
1751             // Retain the legacy behavior of setting SSID to "" if the SSID is all zero values.
1752             this.SSID = "";
1753         } else {
1754             final CharSequence utf8Ssid = (wifiSsid != null) ? wifiSsid.getUtf8Text() : null;
1755             this.SSID = (utf8Ssid != null) ? utf8Ssid.toString() : WifiManager.UNKNOWN_SSID;
1756         }
1757         this.BSSID = BSSID;
1758         this.hessid = hessid;
1759         this.anqpDomainId = anqpDomainId;
1760         if (osuProviders != null) {
1761             this.anqpElements = new AnqpInformationElement[1];
1762             this.anqpElements[0] =
1763                     new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID,
1764                             AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders);
1765         }
1766         this.capabilities = caps;
1767         this.level = level;
1768         this.frequency = frequency;
1769         this.timestamp = tsf;
1770         this.distanceCm = UNSPECIFIED;
1771         this.distanceSdCm = UNSPECIFIED;
1772         this.channelWidth = UNSPECIFIED;
1773         this.centerFreq0 = UNSPECIFIED;
1774         this.centerFreq1 = UNSPECIFIED;
1775         this.flags = 0;
1776         this.radioChainInfos = null;
1777         this.mApMldMacAddress = null;
1778     }
1779 
1780     /**
1781      * @hide
1782      * @deprecated Use {@link ScanResult.Builder}
1783      */
ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency, long tsf, int distCm, int distSdCm)1784     public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency,
1785             long tsf, int distCm, int distSdCm) {
1786         this.wifiSsid = wifiSsid;
1787         if (wifiSsid != null && isHiddenSsid(wifiSsid)) {
1788             // Retain the legacy behavior of setting SSID to "" if the SSID is all zero values.
1789             this.SSID = "";
1790         } else {
1791             final CharSequence utf8Ssid = (wifiSsid != null) ? wifiSsid.getUtf8Text() : null;
1792             this.SSID = (utf8Ssid != null) ? utf8Ssid.toString() : WifiManager.UNKNOWN_SSID;
1793         }
1794         this.BSSID = BSSID;
1795         this.capabilities = caps;
1796         this.level = level;
1797         this.frequency = frequency;
1798         this.timestamp = tsf;
1799         this.distanceCm = distCm;
1800         this.distanceSdCm = distSdCm;
1801         this.channelWidth = UNSPECIFIED;
1802         this.centerFreq0 = UNSPECIFIED;
1803         this.centerFreq1 = UNSPECIFIED;
1804         this.flags = 0;
1805         this.radioChainInfos = null;
1806         this.mApMldMacAddress = null;
1807     }
1808 
1809     /**
1810      * @hide
1811      * @deprecated Use {@link ScanResult.Builder}
1812      */
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)1813     public ScanResult(String Ssid, String BSSID, long hessid, int anqpDomainId, String caps,
1814             int level, int frequency,
1815             long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1,
1816             boolean is80211McRTTResponder) {
1817         this.SSID = Ssid;
1818         this.BSSID = BSSID;
1819         this.hessid = hessid;
1820         this.anqpDomainId = anqpDomainId;
1821         this.capabilities = caps;
1822         this.level = level;
1823         this.frequency = frequency;
1824         this.timestamp = tsf;
1825         this.distanceCm = distCm;
1826         this.distanceSdCm = distSdCm;
1827         this.channelWidth = channelWidth;
1828         this.centerFreq0 = centerFreq0;
1829         this.centerFreq1 = centerFreq1;
1830         if (is80211McRTTResponder) {
1831             this.flags = FLAG_80211mc_RESPONDER;
1832         } else {
1833             this.flags = 0;
1834         }
1835         this.radioChainInfos = null;
1836         this.mApMldMacAddress = null;
1837     }
1838 
1839     /**
1840      * @hide
1841      * @deprecated Use {@link ScanResult.Builder}
1842      */
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)1843     public ScanResult(WifiSsid wifiSsid, String Ssid, String BSSID, long hessid, int anqpDomainId,
1844                   String caps, int level,
1845                   int frequency, long tsf, int distCm, int distSdCm, int channelWidth,
1846                   int centerFreq0, int centerFreq1, boolean is80211McRTTResponder) {
1847         this(Ssid, BSSID, hessid, anqpDomainId, caps, level, frequency, tsf, distCm,
1848                 distSdCm, channelWidth, centerFreq0, centerFreq1, is80211McRTTResponder);
1849         this.wifiSsid = wifiSsid;
1850     }
1851 
1852     /** copy constructor */
ScanResult(@onNull ScanResult source)1853     public ScanResult(@NonNull ScanResult source) {
1854         if (source != null) {
1855             wifiSsid = source.wifiSsid;
1856             SSID = source.SSID;
1857             BSSID = source.BSSID;
1858             hessid = source.hessid;
1859             anqpDomainId = source.anqpDomainId;
1860             informationElements = source.informationElements;
1861             anqpElements = source.anqpElements;
1862             capabilities = source.capabilities;
1863             level = source.level;
1864             frequency = source.frequency;
1865             channelWidth = source.channelWidth;
1866             centerFreq0 = source.centerFreq0;
1867             centerFreq1 = source.centerFreq1;
1868             timestamp = source.timestamp;
1869             distanceCm = source.distanceCm;
1870             distanceSdCm = source.distanceSdCm;
1871             seen = source.seen;
1872             untrusted = source.untrusted;
1873             numUsage = source.numUsage;
1874             venueName = source.venueName;
1875             operatorFriendlyName = source.operatorFriendlyName;
1876             flags = source.flags;
1877             radioChainInfos = source.radioChainInfos;
1878             this.mWifiStandard = source.mWifiStandard;
1879             this.ifaceName = source.ifaceName;
1880             this.mApMldMacAddress = source.mApMldMacAddress;
1881             this.mApMloLinkId = source.mApMloLinkId;
1882             this.mAffiliatedMloLinks = source.mAffiliatedMloLinks != null
1883                     ? new ArrayList<>(source.mAffiliatedMloLinks) : Collections.emptyList();
1884         }
1885     }
1886 
1887     /** Construct an empty scan result. */
ScanResult()1888     public ScanResult() {
1889     }
1890 
1891     @Override
toString()1892     public String toString() {
1893         StringBuffer sb = new StringBuffer();
1894         String none = "<none>";
1895 
1896         sb.append("SSID: ")
1897                 .append(wifiSsid == null ? WifiManager.UNKNOWN_SSID : wifiSsid)
1898                 .append(", BSSID: ")
1899                 .append(BSSID == null ? none : BSSID)
1900                 .append(", capabilities: ")
1901                 .append(capabilities == null ? none : capabilities)
1902                 .append(", level: ")
1903                 .append(level)
1904                 .append(", frequency: ")
1905                 .append(frequency)
1906                 .append(", timestamp: ")
1907                 .append(timestamp);
1908         sb.append(", distance: ").append((distanceCm != UNSPECIFIED ? distanceCm : "?")).
1909                 append("(cm)");
1910         sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")).
1911                 append("(cm)");
1912 
1913         sb.append(", passpoint: ");
1914         sb.append(((flags & FLAG_PASSPOINT_NETWORK) != 0) ? "yes" : "no");
1915         sb.append(", ChannelBandwidth: ").append(channelWidth);
1916         sb.append(", centerFreq0: ").append(centerFreq0);
1917         sb.append(", centerFreq1: ").append(centerFreq1);
1918         sb.append(", standard: ").append(wifiStandardToString(mWifiStandard));
1919         sb.append(", 80211mcResponder: ");
1920         sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported");
1921         sb.append(", 80211azNtbResponder: ");
1922         sb.append(
1923                 ((flags & FLAG_80211az_NTB_RESPONDER) != 0) ? "is supported" : "is not supported");
1924         sb.append(", TWT Responder: ");
1925         sb.append(((flags & FLAG_TWT_RESPONDER) != 0) ? "yes" : "no");
1926         sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos));
1927         sb.append(", interface name: ").append(ifaceName);
1928 
1929         if (mApMldMacAddress != null) {
1930             sb.append(", MLO Info: ")
1931                     .append(" AP MLD MAC Address: ")
1932                     .append(mApMldMacAddress.toString())
1933                     .append(", AP MLO Link-Id: ")
1934                     .append((mApMloLinkId == MloLink.INVALID_MLO_LINK_ID)
1935                             ? "Unspecified" : mApMloLinkId)
1936                     .append(", AP MLO Affiliated Links: ").append(mAffiliatedMloLinks);
1937         }
1938 
1939         return sb.toString();
1940     }
1941 
1942     /** Implement the Parcelable interface {@hide} */
describeContents()1943     public int describeContents() {
1944         return 0;
1945     }
1946 
1947     /** Implement the Parcelable interface {@hide} */
writeToParcel(Parcel dest, int flags)1948     public void writeToParcel(Parcel dest, int flags) {
1949         long start = dest.dataSize();
1950         if (wifiSsid != null) {
1951             dest.writeInt(1);
1952             wifiSsid.writeToParcel(dest, flags);
1953         } else {
1954             dest.writeInt(0);
1955         }
1956         dest.writeString(SSID);
1957         dest.writeString(BSSID);
1958         dest.writeLong(hessid);
1959         dest.writeInt(anqpDomainId);
1960         dest.writeString(capabilities);
1961         dest.writeInt(level);
1962         dest.writeInt(frequency);
1963         dest.writeLong(timestamp);
1964         dest.writeInt(distanceCm);
1965         dest.writeInt(distanceSdCm);
1966         dest.writeInt(channelWidth);
1967         dest.writeInt(centerFreq0);
1968         dest.writeInt(centerFreq1);
1969         dest.writeInt(mWifiStandard);
1970         dest.writeLong(seen);
1971         dest.writeInt(untrusted ? 1 : 0);
1972         dest.writeInt(numUsage);
1973         dest.writeString((venueName != null) ? venueName.toString() : "");
1974         dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : "");
1975         dest.writeLong(this.flags);
1976         dest.writeTypedArray(informationElements, flags);
1977 
1978         if (anqpLines != null) {
1979             dest.writeInt(anqpLines.size());
1980             for (int i = 0; i < anqpLines.size(); i++) {
1981                 dest.writeString(anqpLines.get(i));
1982             }
1983         }
1984         else {
1985             dest.writeInt(0);
1986         }
1987         int anqpElementsPayloadSize = 0;
1988         if (anqpElements != null) {
1989             dest.writeInt(anqpElements.length);
1990             for (AnqpInformationElement element : anqpElements) {
1991                 dest.writeInt(element.getVendorId());
1992                 dest.writeInt(element.getElementId());
1993                 dest.writeInt(element.getPayload().length);
1994                 dest.writeByteArray(element.getPayload());
1995                 anqpElementsPayloadSize += element.getPayload().length;
1996             }
1997         } else {
1998             dest.writeInt(0);
1999         }
2000 
2001         if (radioChainInfos != null) {
2002             dest.writeInt(radioChainInfos.length);
2003             for (int i = 0; i < radioChainInfos.length; i++) {
2004                 dest.writeInt(radioChainInfos[i].id);
2005                 dest.writeInt(radioChainInfos[i].level);
2006             }
2007         } else {
2008             dest.writeInt(0);
2009         }
2010         dest.writeString((ifaceName != null) ? ifaceName.toString() : "");
2011 
2012 
2013         // Add MLO related attributes
2014         dest.writeParcelable(mApMldMacAddress, flags);
2015         dest.writeInt(mApMloLinkId);
2016         dest.writeTypedList(mAffiliatedMloLinks);
2017         if (dest.dataSize() - start > 10000) {
2018             Log.e(
2019                     TAG,
2020                     " Abnormal ScanResult: "
2021                             + this
2022                             + ". The size is "
2023                             + (dest.dataSize() - start)
2024                             + ". The informationElements size is "
2025                             + informationElements.length
2026                             + ". The anqpPayload size is "
2027                             + anqpElementsPayloadSize);
2028         }
2029     }
2030 
2031     /** Implement the Parcelable interface */
2032     public static final @NonNull Creator<ScanResult> CREATOR =
2033             new Creator<ScanResult>() {
2034                 public ScanResult createFromParcel(Parcel in) {
2035                     WifiSsid wifiSsid = null;
2036                     if (in.readInt() == 1) {
2037                         wifiSsid = WifiSsid.CREATOR.createFromParcel(in);
2038                     }
2039                     ScanResult sr = new ScanResult(
2040                             wifiSsid,
2041                             in.readString(),                    /* SSID  */
2042                             in.readString(),                    /* BSSID */
2043                             in.readLong(),                      /* HESSID */
2044                             in.readInt(),                       /* ANQP Domain ID */
2045                             in.readString(),                    /* capabilities */
2046                             in.readInt(),                       /* level */
2047                             in.readInt(),                       /* frequency */
2048                             in.readLong(),                      /* timestamp */
2049                             in.readInt(),                       /* distanceCm */
2050                             in.readInt(),                       /* distanceSdCm */
2051                             in.readInt(),                       /* channelWidth */
2052                             in.readInt(),                       /* centerFreq0 */
2053                             in.readInt(),                       /* centerFreq1 */
2054                             false                               /* rtt responder,
2055                                                                fixed with flags below */
2056                     );
2057 
2058                     sr.mWifiStandard = in.readInt();
2059                     sr.seen = in.readLong();
2060                     sr.untrusted = in.readInt() != 0;
2061                     sr.numUsage = in.readInt();
2062                     sr.venueName = in.readString();
2063                     sr.operatorFriendlyName = in.readString();
2064                     sr.flags = in.readLong();
2065                     sr.informationElements = in.createTypedArray(InformationElement.CREATOR);
2066 
2067                     int n = in.readInt();
2068                     if (n != 0) {
2069                         sr.anqpLines = new ArrayList<String>();
2070                         for (int i = 0; i < n; i++) {
2071                             sr.anqpLines.add(in.readString());
2072                         }
2073                     }
2074                     n = in.readInt();
2075                     if (n != 0) {
2076                         sr.anqpElements = new AnqpInformationElement[n];
2077                         for (int i = 0; i < n; i++) {
2078                             int vendorId = in.readInt();
2079                             int elementId = in.readInt();
2080                             int len = in.readInt();
2081                             byte[] payload = new byte[len];
2082                             in.readByteArray(payload);
2083                             sr.anqpElements[i] =
2084                                     new AnqpInformationElement(vendorId, elementId, payload);
2085                         }
2086                     }
2087                     n = in.readInt();
2088                     if (n != 0) {
2089                         sr.radioChainInfos = new RadioChainInfo[n];
2090                         for (int i = 0; i < n; i++) {
2091                             sr.radioChainInfos[i] = new RadioChainInfo();
2092                             sr.radioChainInfos[i].id = in.readInt();
2093                             sr.radioChainInfos[i].level = in.readInt();
2094                         }
2095                     }
2096                     sr.ifaceName = in.readString();
2097 
2098                     // Read MLO related attributes
2099                     sr.mApMldMacAddress = in.readParcelable(MacAddress.class.getClassLoader());
2100                     sr.mApMloLinkId = in.readInt();
2101                     sr.mAffiliatedMloLinks = in.createTypedArrayList(MloLink.CREATOR);
2102 
2103                     return sr;
2104                 }
2105             public ScanResult[] newArray(int size) {
2106                 return new ScanResult[size];
2107             }
2108         };
2109 }
2110