• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.wifi;
18 
19 import android.annotation.IntDef;
20 import android.annotation.IntRange;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SystemApi;
24 import android.compat.annotation.UnsupportedAppUsage;
25 import android.net.MacAddress;
26 import android.net.wifi.WifiAnnotations.ChannelWidth;
27 import android.net.wifi.WifiAnnotations.WifiStandard;
28 import android.net.wifi.util.ScanResultUtil;
29 import android.os.Build;
30 import android.os.Parcel;
31 import android.os.Parcelable;
32 
33 import com.android.modules.utils.build.SdkLevel;
34 
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 import java.nio.ByteBuffer;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Collections;
41 import java.util.List;
42 import java.util.Objects;
43 
44 /**
45  * Describes information about a detected access point. In addition
46  * to the attributes described here, the supplicant keeps track of
47  * {@code quality}, {@code noise}, and {@code maxbitrate} attributes,
48  * but does not currently report them to external clients.
49  */
50 public final class ScanResult implements Parcelable {
51     /**
52      * The network name.
53      *
54      * @deprecated Use {@link #getWifiSsid()} instead.
55      */
56     @Deprecated
57     public String SSID;
58 
59     /**
60      * Ascii encoded SSID. This will replace SSID when we deprecate it. @hide
61      *
62      * @deprecated Use {@link #getWifiSsid()} instead.
63      */
64     @Deprecated
65     // TODO(b/231433398): add maxTargetSdk = Build.VERSION_CODES.S
66     @UnsupportedAppUsage(publicAlternatives = "{@link #getWifiSsid()}")
67     public WifiSsid wifiSsid;
68 
69     /**
70      * Set the SSID of the access point.
71      * @hide
72      */
73     @SystemApi
setWifiSsid(@onNull WifiSsid ssid)74     public void setWifiSsid(@NonNull WifiSsid ssid) {
75         wifiSsid = ssid;
76         CharSequence utf8Text = wifiSsid.getUtf8Text();
77         SSID = utf8Text != null ? utf8Text.toString() : WifiManager.UNKNOWN_SSID;
78     }
79 
80     /**
81      * The SSID of the access point.
82      */
83     @Nullable
getWifiSsid()84     public WifiSsid getWifiSsid() {
85         return wifiSsid;
86     }
87 
88     /**
89      * The address of the access point.
90      */
91     public String BSSID;
92 
93     /**
94      * The Multi-Link Device (MLD) address of the access point.
95      * Only applicable for Wi-Fi 7 access points, null otherwise.
96      */
97     private MacAddress mApMldMacAddress;
98 
99     /**
100      * Return the access point Multi-Link Device (MLD) MAC Address for Wi-Fi 7 access points.
101      * i.e. {@link #getWifiStandard()} returns {@link #WIFI_STANDARD_11BE}.
102      *
103      * @return MLD MAC Address for access point if exists (Wi-Fi 7 access points), null otherwise.
104      */
105     @Nullable
getApMldMacAddress()106     public MacAddress getApMldMacAddress() {
107         return mApMldMacAddress;
108     }
109 
110     /**
111      * Set the access point Multi-Link Device (MLD) MAC Address.
112      * @hide
113      */
setApMldMacAddress(@ullable MacAddress address)114     public void setApMldMacAddress(@Nullable MacAddress address) {
115         mApMldMacAddress = address;
116     }
117 
118     /**
119      * The Multi-Link Operation (MLO) link id for the access point.
120      * Only applicable for Wi-Fi 7 access points.
121      */
122     private int mApMloLinkId = MloLink.INVALID_MLO_LINK_ID;
123 
124     /**
125      * Return the access point Multi-Link Operation (MLO) link-id for Wi-Fi 7 access points.
126      * i.e. when {@link #getWifiStandard()} returns {@link #WIFI_STANDARD_11BE}, otherwise return
127      * {@link MloLink#INVALID_MLO_LINK_ID}.
128      *
129      * Valid values are 0-15 as described in IEEE 802.11be Specification, section 9.4.2.295b.2.
130      *
131      * @return {@link MloLink#INVALID_MLO_LINK_ID} or a valid value (0-15).
132      */
133     @IntRange(from = MloLink.INVALID_MLO_LINK_ID, to = MloLink.MAX_MLO_LINK_ID)
getApMloLinkId()134     public int getApMloLinkId() {
135         return mApMloLinkId;
136     }
137 
138     /**
139      * Sets the access point Multi-Link Operation (MLO) link-id
140      * @hide
141      */
setApMloLinkId(int linkId)142     public void setApMloLinkId(int linkId) {
143         mApMloLinkId = linkId;
144     }
145 
146     /**
147      * The Multi-Link Operation (MLO) affiliated Links.
148      * Only applicable for Wi-Fi 7 access points.
149      * Note: the list of links includes the access point for this ScanResult.
150      */
151     private List<MloLink> mAffiliatedMloLinks = Collections.emptyList();
152 
153     /**
154      * Return the Multi-Link Operation (MLO) affiliated Links for Wi-Fi 7 access points.
155      * i.e. when {@link #getWifiStandard()} returns {@link #WIFI_STANDARD_11BE}.
156      *
157      * @return List of affiliated MLO links, or an empty list if access point is not Wi-Fi 7
158      */
159     @NonNull
getAffiliatedMloLinks()160     public List<MloLink> getAffiliatedMloLinks() {
161         return new ArrayList<MloLink>(mAffiliatedMloLinks);
162     }
163 
164     /**
165      * Set the Multi-Link Operation (MLO) affiliated Links.
166      * Only applicable for Wi-Fi 7 access points.
167      *
168      * @hide
169      */
setAffiliatedMloLinks(@onNull List<MloLink> links)170     public void setAffiliatedMloLinks(@NonNull List<MloLink> links) {
171         mAffiliatedMloLinks = new ArrayList<MloLink>(links);
172     }
173 
174     /**
175      * The HESSID from the beacon.
176      * @hide
177      */
178     @UnsupportedAppUsage
179     public long hessid;
180 
181     /**
182      * The ANQP Domain ID from the Hotspot 2.0 Indication element, if present.
183      * @hide
184      */
185     @UnsupportedAppUsage
186     public int anqpDomainId;
187 
188     /*
189      * This field is equivalent to the |flags|, rather than the |capabilities| field
190      * of the per-BSS scan results returned by WPA supplicant. See the definition of
191      * |struct wpa_bss| in wpa_supplicant/bss.h for more details.
192      */
193     /**
194      * Describes the authentication, key management, and encryption schemes
195      * supported by the access point.
196      */
197     public String capabilities;
198 
199     /**
200      * The interface name on which the scan result was received.
201      * @hide
202      */
203     public String ifaceName;
204 
205     /**
206      * @hide
207      * No security protocol.
208      */
209     @SystemApi
210     public static final int PROTOCOL_NONE = 0;
211     /**
212      * @hide
213      * Security protocol type: WPA version 1.
214      */
215     @SystemApi
216     public static final int PROTOCOL_WPA = 1;
217     /**
218      * @hide
219      * Security protocol type: RSN, for WPA version 2, and version 3.
220      */
221     @SystemApi
222     public static final int PROTOCOL_RSN = 2;
223     /**
224      * @hide
225      * Security protocol type:
226      * OSU Server-only authenticated layer 2 Encryption Network.
227      * Used for Hotspot 2.0.
228      */
229     @SystemApi
230     public static final int PROTOCOL_OSEN = 3;
231 
232     /**
233      * @hide
234      * Security protocol type: WAPI.
235      */
236     @SystemApi
237     public static final int PROTOCOL_WAPI = 4;
238 
239     /**
240      * @hide
241      * No security key management scheme.
242      */
243     @SystemApi
244     public static final int KEY_MGMT_NONE = 0;
245     /**
246      * @hide
247      * Security key management scheme: PSK.
248      */
249     @SystemApi
250     public static final int KEY_MGMT_PSK = 1;
251     /**
252      * @hide
253      * Security key management scheme: EAP.
254      */
255     @SystemApi
256     public static final int KEY_MGMT_EAP = 2;
257     /**
258      * @hide
259      * Security key management scheme: FT_PSK.
260      */
261     @SystemApi
262     public static final int KEY_MGMT_FT_PSK = 3;
263     /**
264      * @hide
265      * Security key management scheme: FT_EAP.
266      */
267     @SystemApi
268     public static final int KEY_MGMT_FT_EAP = 4;
269     /**
270      * @hide
271      * Security key management scheme: PSK_SHA256
272      */
273     @SystemApi
274     public static final int KEY_MGMT_PSK_SHA256 = 5;
275     /**
276      * @hide
277      * Security key management scheme: EAP_SHA256.
278      */
279     @SystemApi
280     public static final int KEY_MGMT_EAP_SHA256 = 6;
281     /**
282      * @hide
283      * Security key management scheme: OSEN.
284      * Used for Hotspot 2.0.
285      */
286     @SystemApi
287     public static final int KEY_MGMT_OSEN = 7;
288      /**
289      * @hide
290      * Security key management scheme: SAE.
291      */
292     @SystemApi
293     public static final int KEY_MGMT_SAE = 8;
294     /**
295      * @hide
296      * Security key management scheme: OWE.
297      */
298     @SystemApi
299     public static final int KEY_MGMT_OWE = 9;
300     /**
301      * @hide
302      * Security key management scheme: SUITE_B_192.
303      */
304     @SystemApi
305     public static final int KEY_MGMT_EAP_SUITE_B_192 = 10;
306     /**
307      * @hide
308      * Security key management scheme: FT_SAE.
309      */
310     @SystemApi
311     public static final int KEY_MGMT_FT_SAE = 11;
312     /**
313      * @hide
314      * Security key management scheme: OWE in transition mode.
315      */
316     @SystemApi
317     public static final int KEY_MGMT_OWE_TRANSITION = 12;
318     /**
319      * @hide
320      * Security key management scheme: WAPI_PSK.
321      */
322     @SystemApi
323     public static final int KEY_MGMT_WAPI_PSK = 13;
324     /**
325      * @hide
326      * Security key management scheme: WAPI_CERT.
327      */
328     @SystemApi
329     public static final int KEY_MGMT_WAPI_CERT = 14;
330 
331     /**
332      * @hide
333      * Security key management scheme: FILS_SHA256.
334      */
335     public static final int KEY_MGMT_FILS_SHA256 = 15;
336     /**
337      * @hide
338      * Security key management scheme: FILS_SHA384.
339      */
340     public static final int KEY_MGMT_FILS_SHA384 = 16;
341     /**
342      * @hide
343      * Security key management scheme: DPP.
344      */
345     public static final int KEY_MGMT_DPP = 17;
346     /**
347      * @hide
348      * Security key management scheme: any unknown AKM.
349      */
350     public static final int KEY_MGMT_UNKNOWN = 18;
351     /**
352      * @hide
353      * No cipher suite.
354      */
355     @SystemApi
356     public static final int CIPHER_NONE = 0;
357     /**
358      * @hide
359      * No group addressed, only used for group data cipher.
360      */
361     @SystemApi
362     public static final int CIPHER_NO_GROUP_ADDRESSED = 1;
363     /**
364      * @hide
365      * Cipher suite: TKIP
366      */
367     @SystemApi
368     public static final int CIPHER_TKIP = 2;
369     /**
370      * @hide
371      * Cipher suite: CCMP
372      */
373     @SystemApi
374     public static final int CIPHER_CCMP = 3;
375     /**
376      * @hide
377      * Cipher suite: GCMP
378      */
379     @SystemApi
380     public static final int CIPHER_GCMP_256 = 4;
381     /**
382      * @hide
383      * Cipher suite: SMS4
384      */
385     @SystemApi
386     public static final int CIPHER_SMS4 = 5;
387     /**
388      * @hide
389      * Cipher suite: GCMP_128
390      */
391     @SystemApi
392     public static final int CIPHER_GCMP_128 = 6;
393     /**
394      * @hide
395      * Cipher suite: BIP_GMAC_128
396      */
397     @SystemApi
398     public static final int CIPHER_BIP_GMAC_128 = 7;
399     /**
400      * @hide
401      * Cipher suite: BIP_GMAC_256
402      */
403     @SystemApi
404     public static final int CIPHER_BIP_GMAC_256 = 8;
405     /**
406      * @hide
407      * Cipher suite: BIP_CMAC_256
408      */
409     @SystemApi
410     public static final int CIPHER_BIP_CMAC_256 = 9;
411 
412     /**
413      * The detected signal level in dBm, also known as the RSSI.
414      *
415      * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
416      * an absolute signal level which can be displayed to a user.
417      */
418     public int level;
419 
420     /**
421      * The center frequency of the primary 20 MHz frequency (in MHz) of the channel over which the
422      * client is communicating with the access point.
423      */
424     public int frequency;
425 
426    /**
427     * AP Channel bandwidth is 20 MHZ
428     */
429     public static final int CHANNEL_WIDTH_20MHZ = 0;
430    /**
431     * AP Channel bandwidth is 40 MHZ
432     */
433     public static final int CHANNEL_WIDTH_40MHZ = 1;
434    /**
435     * AP Channel bandwidth is 80 MHZ
436     */
437     public static final int CHANNEL_WIDTH_80MHZ = 2;
438    /**
439     * AP Channel bandwidth is 160 MHZ
440     */
441     public static final int CHANNEL_WIDTH_160MHZ = 3;
442    /**
443     * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ
444     */
445     public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4;
446    /**
447     * AP Channel bandwidth is 320 MHZ
448     */
449     public static final int CHANNEL_WIDTH_320MHZ = 5;
450 
451     /**
452      * Preamble type: Legacy.
453      */
454     public static final int PREAMBLE_LEGACY = 0;
455     /**
456      * Preamble type: HT.
457      */
458     public static final int PREAMBLE_HT = 1;
459     /**
460      * Preamble type: VHT.
461      */
462     public static final int PREAMBLE_VHT = 2;
463     /**
464      * Preamble type: HE.
465      */
466     public static final int PREAMBLE_HE = 3;
467 
468     /**
469      * Preamble type: EHT.
470      */
471     public static final int PREAMBLE_EHT = 4;
472 
473     /**
474      * Wi-Fi unknown standard
475      */
476     public static final int WIFI_STANDARD_UNKNOWN = 0;
477 
478     /**
479      * Wi-Fi 802.11a/b/g
480      */
481     public static final int WIFI_STANDARD_LEGACY = 1;
482 
483     /**
484      * Wi-Fi 802.11n
485      */
486     public static final int WIFI_STANDARD_11N = 4;
487 
488     /**
489      * Wi-Fi 802.11ac
490      */
491     public static final int WIFI_STANDARD_11AC = 5;
492 
493     /**
494      * Wi-Fi 802.11ax
495      */
496     public static final int WIFI_STANDARD_11AX = 6;
497 
498     /**
499      * Wi-Fi 802.11ad
500      */
501     public static final int WIFI_STANDARD_11AD = 7;
502 
503     /**
504      * Wi-Fi 802.11be
505      */
506     public static final int WIFI_STANDARD_11BE = 8;
507 
508     /**
509      * Wi-Fi 2.4 GHz band.
510      */
511     public static final int WIFI_BAND_24_GHZ = WifiScanner.WIFI_BAND_24_GHZ;
512 
513     /**
514      * Wi-Fi 5 GHz band.
515      */
516     public static final int WIFI_BAND_5_GHZ = WifiScanner.WIFI_BAND_5_GHZ;
517 
518     /**
519      * Wi-Fi 6 GHz band.
520      */
521     public static final int WIFI_BAND_6_GHZ = WifiScanner.WIFI_BAND_6_GHZ;
522 
523     /**
524      * Wi-Fi 60 GHz band.
525      */
526     public static final int WIFI_BAND_60_GHZ = WifiScanner.WIFI_BAND_60_GHZ;
527 
528     /**
529      * @hide
530      */
531     @Retention(RetentionPolicy.SOURCE)
532     @IntDef(prefix = {"WIFI_BAND_"}, value = {
533             UNSPECIFIED,
534             WIFI_BAND_24_GHZ,
535             WIFI_BAND_5_GHZ,
536             WIFI_BAND_6_GHZ,
537             WIFI_BAND_60_GHZ})
538     public @interface WifiBand {};
539 
540     /**
541      * AP wifi standard.
542      */
543     private @WifiStandard int mWifiStandard = WIFI_STANDARD_UNKNOWN;
544 
545     /**
546      * return the AP wifi standard.
547      */
getWifiStandard()548     public @WifiStandard int getWifiStandard() {
549         return mWifiStandard;
550     }
551 
552     /**
553      * sets the AP wifi standard.
554      * @hide
555      */
setWifiStandard(@ifiStandard int standard)556     public void setWifiStandard(@WifiStandard int standard) {
557         mWifiStandard = standard;
558     }
559 
560     /**
561      * Convert Wi-Fi standard to string
562      */
wifiStandardToString(@ifiStandard int standard)563     private static @Nullable String wifiStandardToString(@WifiStandard int standard) {
564         switch(standard) {
565             case WIFI_STANDARD_LEGACY:
566                 return "legacy";
567             case WIFI_STANDARD_11N:
568                 return "11n";
569             case WIFI_STANDARD_11AC:
570                 return "11ac";
571             case WIFI_STANDARD_11AX:
572                 return "11ax";
573             case WIFI_STANDARD_11AD:
574                 return "11ad";
575             case WIFI_STANDARD_11BE:
576                 return "11be";
577             case WIFI_STANDARD_UNKNOWN:
578                 return "unknown";
579         }
580         return null;
581     }
582 
583     /**
584      * AP Channel bandwidth; one of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
585      * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ}, {@link #CHANNEL_WIDTH_320MHZ},
586      * or {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}, or {@link #CHANNEL_WIDTH_320MHZ}
587      */
588     public @ChannelWidth int channelWidth;
589 
590     /**
591      * Not used if the AP bandwidth is 20 MHz
592      * If the AP use 40, 80, 160 or 320MHz, this is the center frequency (in MHz)
593      * if the AP use 80 + 80 MHz, this is the center frequency of the first segment (in MHz)
594      */
595     public int centerFreq0;
596 
597     /**
598      * Only used if the AP bandwidth is 80 + 80 MHz
599      * if the AP use 80 + 80 MHz, this is the center frequency of the second segment (in MHz)
600      */
601     public int centerFreq1;
602 
603     /**
604      * @deprecated use is80211mcResponder() instead
605      * @hide
606      */
607     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
608     public boolean is80211McRTTResponder;
609 
610     /**
611      * timestamp in microseconds (since boot) when
612      * this result was last seen.
613      */
614     public long timestamp;
615 
616     /**
617      * Timestamp representing date when this result was last seen, in milliseconds from 1970
618      * {@hide}
619      */
620     @UnsupportedAppUsage
621     public long seen;
622 
623     /**
624      * On devices with multiple hardware radio chains, this class provides metadata about
625      * each radio chain that was used to receive this scan result (probe response or beacon).
626      * {@hide}
627      */
628     public static class RadioChainInfo {
629         /** Vendor defined id for a radio chain. */
630         public int id;
631         /** Detected signal level in dBm (also known as the RSSI) on this radio chain. */
632         public int level;
633 
634         @Override
toString()635         public String toString() {
636             return "RadioChainInfo: id=" + id + ", level=" + level;
637         }
638 
639         @Override
equals(Object otherObj)640         public boolean equals(Object otherObj) {
641             if (this == otherObj) {
642                 return true;
643             }
644             if (!(otherObj instanceof RadioChainInfo)) {
645                 return false;
646             }
647             RadioChainInfo other = (RadioChainInfo) otherObj;
648             return id == other.id && level == other.level;
649         }
650 
651         @Override
hashCode()652         public int hashCode() {
653             return Objects.hash(id, level);
654         }
655     };
656 
657     /**
658      * Information about the list of the radio chains used to receive this scan result
659      * (probe response or beacon).
660      *
661      * For Example: On devices with 2 hardware radio chains, this list could hold 1 or 2
662      * entries based on whether this scan result was received using one or both the chains.
663      * {@hide}
664      */
665     public RadioChainInfo[] radioChainInfos;
666 
667     /**
668      * Status indicating the scan result does not correspond to a user's saved configuration
669      * @hide
670      * @removed
671      */
672     @SystemApi
673     public boolean untrusted;
674 
675     /**
676      * Number of time autojoin used it
677      * @hide
678      */
679     @UnsupportedAppUsage
680     public int numUsage;
681 
682     /**
683      * The approximate distance to the AP in centimeter, if available.  Else
684      * {@link #UNSPECIFIED}.
685      * {@hide}
686      */
687     @UnsupportedAppUsage
688     public int distanceCm;
689 
690     /**
691      * The standard deviation of the distance to the access point, if available.
692      * Else {@link #UNSPECIFIED}.
693      * {@hide}
694      */
695     @UnsupportedAppUsage
696     public int distanceSdCm;
697 
698     /** {@hide} */
699     public static final long FLAG_PASSPOINT_NETWORK               = 0x0000000000000001;
700 
701     /** {@hide} */
702     public static final long FLAG_80211mc_RESPONDER               = 0x0000000000000002;
703 
704     /*
705      * These flags are specific to the ScanResult class, and are not related to the |flags|
706      * field of the per-BSS scan results from WPA supplicant.
707      */
708     /**
709      * Defines flags; such as {@link #FLAG_PASSPOINT_NETWORK}.
710      * {@hide}
711      */
712     @UnsupportedAppUsage
713     public long flags;
714 
715     /**
716      * sets a flag in {@link #flags} field
717      * @param flag flag to set
718      * @hide
719      */
setFlag(long flag)720     public void setFlag(long flag) {
721         flags |= flag;
722     }
723 
724     /**
725      * clears a flag in {@link #flags} field
726      * @param flag flag to set
727      * @hide
728      */
clearFlag(long flag)729     public void clearFlag(long flag) {
730         flags &= ~flag;
731     }
732 
is80211mcResponder()733     public boolean is80211mcResponder() {
734         return (flags & FLAG_80211mc_RESPONDER) != 0;
735     }
736 
isPasspointNetwork()737     public boolean isPasspointNetwork() {
738         return (flags & FLAG_PASSPOINT_NETWORK) != 0;
739     }
740 
741     /**
742      * Indicates venue name (such as 'San Francisco Airport') published by access point; only
743      * available on Passpoint network and if published by access point.
744      * @deprecated - This information is not provided
745      */
746     @Deprecated
747     public CharSequence venueName;
748 
749     /**
750      * Indicates Passpoint operator name published by access point.
751      * @deprecated - Use {@link WifiInfo#getPasspointProviderFriendlyName()}
752      */
753     @Deprecated
754     public CharSequence operatorFriendlyName;
755 
756     /**
757      * The unspecified value.
758      */
759     public final static int UNSPECIFIED = -1;
760 
761     /**
762      * 2.4 GHz band first channel number
763      * @hide
764      */
765     public static final int BAND_24_GHZ_FIRST_CH_NUM = 1;
766     /**
767      * 2.4 GHz band last channel number
768      * @hide
769      */
770     public static final int BAND_24_GHZ_LAST_CH_NUM = 14;
771     /**
772      * 2.4 GHz band frequency of first channel in MHz
773      * @hide
774      */
775     public static final int BAND_24_GHZ_START_FREQ_MHZ = 2412;
776     /**
777      * 2.4 GHz band frequency of last channel in MHz
778      * @hide
779      */
780     public static final int BAND_24_GHZ_END_FREQ_MHZ = 2484;
781 
782     /**
783      * 5 GHz band first channel number
784      * @hide
785      */
786     public static final int BAND_5_GHZ_FIRST_CH_NUM = 32;
787     /**
788      * 5 GHz band last channel number
789      * @hide
790      */
791     public static final int BAND_5_GHZ_LAST_CH_NUM = 177;
792     /**
793      * 5 GHz band frequency of first channel in MHz
794      * @hide
795      */
796     public static final int BAND_5_GHZ_START_FREQ_MHZ = 5160;
797     /**
798      * 5 GHz band frequency of last channel in MHz
799      * @hide
800      */
801     public static final int BAND_5_GHZ_END_FREQ_MHZ = 5885;
802 
803     /**
804      * 6 GHz band first channel number
805      * @hide
806      */
807     public static final int BAND_6_GHZ_FIRST_CH_NUM = 1;
808     /**
809      * 6 GHz band last channel number
810      * @hide
811      */
812     public static final int BAND_6_GHZ_LAST_CH_NUM = 233;
813     /**
814      * 6 GHz band frequency of first channel in MHz
815      * @hide
816      */
817     public static final int BAND_6_GHZ_START_FREQ_MHZ = 5955;
818     /**
819      * 6 GHz band frequency of last channel in MHz
820      * @hide
821      */
822     public static final int BAND_6_GHZ_END_FREQ_MHZ = 7115;
823     /**
824      * The center frequency of the first 6Ghz preferred scanning channel, as defined by
825      * IEEE802.11ax draft 7.0 section 26.17.2.3.3.
826      * @hide
827      */
828     public static final int BAND_6_GHZ_PSC_START_MHZ = 5975;
829     /**
830      * The number of MHz to increment in order to get the next 6Ghz preferred scanning channel
831      * as defined by IEEE802.11ax draft 7.0 section 26.17.2.3.3.
832      * @hide
833      */
834     public static final int BAND_6_GHZ_PSC_STEP_SIZE_MHZ = 80;
835 
836     /**
837      * 6 GHz band operating class 136 channel 2 center frequency in MHz
838      * @hide
839      */
840     public static final int BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ = 5935;
841 
842     /**
843      * 60 GHz band first channel number
844      * @hide
845      */
846     public static final int BAND_60_GHZ_FIRST_CH_NUM = 1;
847     /**
848      * 60 GHz band last channel number
849      * @hide
850      */
851     public static final int BAND_60_GHZ_LAST_CH_NUM = 6;
852     /**
853      * 60 GHz band frequency of first channel in MHz
854      * @hide
855      */
856     public static final int BAND_60_GHZ_START_FREQ_MHZ = 58320;
857     /**
858      * 60 GHz band frequency of last channel in MHz
859      * @hide
860      */
861     public static final int BAND_60_GHZ_END_FREQ_MHZ = 70200;
862 
863     /**
864      * Utility function to check if a frequency within 2.4 GHz band
865      * @param freqMhz frequency in MHz
866      * @return true if within 2.4GHz, false otherwise
867      *
868      * @hide
869      */
is24GHz(int freqMhz)870     public static boolean is24GHz(int freqMhz) {
871         return freqMhz >= BAND_24_GHZ_START_FREQ_MHZ && freqMhz <= BAND_24_GHZ_END_FREQ_MHZ;
872     }
873 
874     /**
875      * Utility function to check if a frequency within 5 GHz band
876      * @param freqMhz frequency in MHz
877      * @return true if within 5GHz, false otherwise
878      *
879      * @hide
880      */
is5GHz(int freqMhz)881     public static boolean is5GHz(int freqMhz) {
882         return freqMhz >=  BAND_5_GHZ_START_FREQ_MHZ && freqMhz <= BAND_5_GHZ_END_FREQ_MHZ;
883     }
884 
885     /**
886      * Utility function to check if a frequency within 6 GHz band
887      * @param freqMhz
888      * @return true if within 6GHz, false otherwise
889      *
890      * @hide
891      */
is6GHz(int freqMhz)892     public static boolean is6GHz(int freqMhz) {
893         if (freqMhz == BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ) {
894             return true;
895         }
896         return (freqMhz >= BAND_6_GHZ_START_FREQ_MHZ && freqMhz <= BAND_6_GHZ_END_FREQ_MHZ);
897     }
898 
899     /**
900      * Utility function to check if a frequency is 6Ghz PSC channel.
901      * @param freqMhz
902      * @return true if the frequency is 6GHz PSC, false otherwise
903      *
904      * @hide
905      */
is6GHzPsc(int freqMhz)906     public static boolean is6GHzPsc(int freqMhz) {
907         if (!ScanResult.is6GHz(freqMhz)) {
908             return false;
909         }
910         return (freqMhz - BAND_6_GHZ_PSC_START_MHZ) % BAND_6_GHZ_PSC_STEP_SIZE_MHZ == 0;
911     }
912 
913     /**
914      * Utility function to check if a frequency within 60 GHz band
915      * @param freqMhz
916      * @return true if within 60GHz, false otherwise
917      *
918      * @hide
919      */
is60GHz(int freqMhz)920     public static boolean is60GHz(int freqMhz) {
921         return freqMhz >= BAND_60_GHZ_START_FREQ_MHZ && freqMhz <= BAND_60_GHZ_END_FREQ_MHZ;
922     }
923 
924     /**
925      * Utility function to convert Wi-Fi channel number to frequency in MHz.
926      *
927      * Reference the Wi-Fi channel numbering and the channelization in IEEE 802.11-2016
928      * specifications, section 17.3.8.4.2, 17.3.8.4.3 and Table 15-6.
929      *
930      * See also {@link #convertFrequencyMhzToChannelIfSupported(int)}.
931      *
932      * @param channel number to convert.
933      * @param band of channel to convert. One of the following bands:
934      *        {@link #WIFI_BAND_24_GHZ},  {@link #WIFI_BAND_5_GHZ},
935      *        {@link #WIFI_BAND_6_GHZ},  {@link #WIFI_BAND_60_GHZ}.
936      * @return center frequency in Mhz of the channel, {@link #UNSPECIFIED} if no match
937      */
convertChannelToFrequencyMhzIfSupported(int channel, @WifiBand int band)938     public static int convertChannelToFrequencyMhzIfSupported(int channel, @WifiBand int band) {
939         if (band == WIFI_BAND_24_GHZ) {
940             // Special case
941             if (channel == 14) {
942                 return 2484;
943             } else if (channel >= BAND_24_GHZ_FIRST_CH_NUM && channel <= BAND_24_GHZ_LAST_CH_NUM) {
944                 return ((channel - BAND_24_GHZ_FIRST_CH_NUM) * 5) + BAND_24_GHZ_START_FREQ_MHZ;
945             } else {
946                 return UNSPECIFIED;
947             }
948         }
949         if (band == WIFI_BAND_5_GHZ) {
950             if (channel >= BAND_5_GHZ_FIRST_CH_NUM && channel <= BAND_5_GHZ_LAST_CH_NUM) {
951                 return ((channel - BAND_5_GHZ_FIRST_CH_NUM) * 5) + BAND_5_GHZ_START_FREQ_MHZ;
952             } else {
953                 return UNSPECIFIED;
954             }
955         }
956         if (band == WIFI_BAND_6_GHZ) {
957             if (channel >= BAND_6_GHZ_FIRST_CH_NUM && channel <= BAND_6_GHZ_LAST_CH_NUM) {
958                 if (channel == 2) {
959                     return BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ;
960                 }
961                 return ((channel - BAND_6_GHZ_FIRST_CH_NUM) * 5) + BAND_6_GHZ_START_FREQ_MHZ;
962             } else {
963                 return UNSPECIFIED;
964             }
965         }
966         if (band == WIFI_BAND_60_GHZ) {
967             if (channel >= BAND_60_GHZ_FIRST_CH_NUM && channel <= BAND_60_GHZ_LAST_CH_NUM) {
968                 return ((channel - BAND_60_GHZ_FIRST_CH_NUM) * 2160) + BAND_60_GHZ_START_FREQ_MHZ;
969             } else {
970                 return UNSPECIFIED;
971             }
972         }
973         return UNSPECIFIED;
974     }
975 
976     /**
977      * Utility function to convert Operating Class into a band
978      *
979      * Use 802.11 Specification Table E-4: Global Operating Classes for decoding
980      *
981      * @param opClass operating class
982      * @param channel number
983      *
984      * @return one of {@link WifiScanner.WIFI_BAND_24_GHZ}, {@link WifiScanner.WIFI_BAND_5_GHZ}, or
985      *         {@link WifiScanner.WIFI_BAND_6_GHZ} for a valid opClass, channel pair, otherwise
986      *         {@link WifiScanner.WIFI_BAND_UNSPECIFIED} is returned.
987      *
988      * @hide
989      */
getBandFromOpClass(int opClass, int channel)990     public static int getBandFromOpClass(int opClass, int channel) {
991         if (opClass >= 81 && opClass <= 84) {
992             if (channel >= BAND_24_GHZ_FIRST_CH_NUM && channel <= BAND_24_GHZ_LAST_CH_NUM) {
993                 return WifiScanner.WIFI_BAND_24_GHZ;
994             }
995         } else if (opClass >= 115 && opClass <= 130) {
996             if (channel >= BAND_5_GHZ_FIRST_CH_NUM && channel <= BAND_5_GHZ_LAST_CH_NUM) {
997                 return WifiScanner.WIFI_BAND_5_GHZ;
998             }
999         } else if (opClass >= 131 && opClass <= 137) {
1000             if (channel >= BAND_6_GHZ_FIRST_CH_NUM && channel <= BAND_6_GHZ_LAST_CH_NUM) {
1001                 return WifiScanner.WIFI_BAND_6_GHZ;
1002             }
1003         }
1004 
1005         // If none of the above combinations, then return as invalid band
1006         return WifiScanner.WIFI_BAND_UNSPECIFIED;
1007     }
1008 
1009     /**
1010      * Utility function to convert frequency in MHz to channel number.
1011      *
1012      * See also {@link #convertChannelToFrequencyMhzIfSupported(int, int)}.
1013      *
1014      * @param freqMhz frequency in MHz
1015      * @return channel number associated with given frequency, {@link #UNSPECIFIED} if no match
1016      */
convertFrequencyMhzToChannelIfSupported(int freqMhz)1017     public static int convertFrequencyMhzToChannelIfSupported(int freqMhz) {
1018         // Special case
1019         if (freqMhz == 2484) {
1020             return 14;
1021         } else if (is24GHz(freqMhz)) {
1022             return (freqMhz - BAND_24_GHZ_START_FREQ_MHZ) / 5 + BAND_24_GHZ_FIRST_CH_NUM;
1023         } else if (is5GHz(freqMhz)) {
1024             return ((freqMhz - BAND_5_GHZ_START_FREQ_MHZ) / 5) + BAND_5_GHZ_FIRST_CH_NUM;
1025         } else if (is6GHz(freqMhz)) {
1026             if (freqMhz == BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ) {
1027                 return 2;
1028             }
1029             return ((freqMhz - BAND_6_GHZ_START_FREQ_MHZ) / 5) + BAND_6_GHZ_FIRST_CH_NUM;
1030         } else if (is60GHz(freqMhz)) {
1031             return ((freqMhz - BAND_60_GHZ_START_FREQ_MHZ) / 2160) + BAND_60_GHZ_FIRST_CH_NUM;
1032         }
1033 
1034         return UNSPECIFIED;
1035     }
1036 
1037     /**
1038      * Returns the band for the ScanResult according to its frequency.
1039      * @hide
1040      */
toBand(int frequency)1041     @WifiBand public static int toBand(int frequency) {
1042         if (ScanResult.is24GHz(frequency)) {
1043             return ScanResult.WIFI_BAND_24_GHZ;
1044         } else if (ScanResult.is5GHz(frequency)) {
1045             return ScanResult.WIFI_BAND_5_GHZ;
1046         } else if (ScanResult.is6GHz(frequency)) {
1047             return ScanResult.WIFI_BAND_6_GHZ;
1048         } else if (ScanResult.is60GHz(frequency)) {
1049             return ScanResult.WIFI_BAND_60_GHZ;
1050         }
1051         return ScanResult.UNSPECIFIED;
1052     }
1053 
1054     /**
1055      * Returns the band for the ScanResult according to its frequency.
1056      * @hide
1057      */
1058     @SystemApi
getBand()1059     @WifiBand public int getBand() {
1060         return ScanResult.toBand(this.frequency);
1061     }
1062 
1063     /**
1064      * @hide
1065      */
is24GHz()1066     public boolean is24GHz() {
1067         return ScanResult.is24GHz(frequency);
1068     }
1069 
1070     /**
1071      * @hide
1072      */
is5GHz()1073     public boolean is5GHz() {
1074         return ScanResult.is5GHz(frequency);
1075     }
1076 
1077     /**
1078      * @hide
1079      */
is6GHz()1080     public boolean is6GHz() {
1081         return ScanResult.is6GHz(frequency);
1082     }
1083 
1084     /**
1085      * @hide
1086      */
is6GhzPsc()1087     public boolean is6GhzPsc() {
1088         return ScanResult.is6GHzPsc(frequency);
1089     }
1090 
1091     /**
1092      * @hide
1093      */
is60GHz()1094     public boolean is60GHz() {
1095         return ScanResult.is60GHz(frequency);
1096     }
1097 
1098     /**
1099      *  @hide
1100      * anqp lines from supplicant BSS response
1101      */
1102     @UnsupportedAppUsage
1103     public List<String> anqpLines;
1104 
1105     /**
1106      * information elements from beacon.
1107      */
1108     public static class InformationElement implements Parcelable {
1109         /** @hide */
1110         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1111         public static final int EID_SSID = 0;
1112         /** @hide */
1113         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1114         public static final int EID_SUPPORTED_RATES = 1;
1115         /** @hide */
1116         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1117         public static final int EID_TIM = 5;
1118         /** @hide */
1119         public static final int EID_COUNTRY = 7;
1120         /** @hide */
1121         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1122         public static final int EID_BSS_LOAD = 11;
1123         /** @hide */
1124         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1125         public static final int EID_ERP = 42;
1126         /** @hide */
1127         public static final int EID_HT_CAPABILITIES = 45;
1128         /** @hide */
1129         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1130         public static final int EID_RSN = 48;
1131         /** @hide */
1132         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1133         public static final int EID_EXTENDED_SUPPORTED_RATES = 50;
1134         /** @hide */
1135         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1136         public static final int EID_HT_OPERATION = 61;
1137         /** @hide */
1138         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1139         public static final int EID_INTERWORKING = 107;
1140         /** @hide */
1141         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1142         public static final int EID_ROAMING_CONSORTIUM = 111;
1143         /** @hide */
1144         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1145         public static final int EID_EXTENDED_CAPS = 127;
1146         /** @hide */
1147         public static final int EID_VHT_CAPABILITIES = 191;
1148         /** @hide */
1149         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1150         public static final int EID_VHT_OPERATION = 192;
1151         /** @hide */
1152         public static final int EID_RNR = 201;
1153         /** @hide */
1154         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1155         public static final int EID_VSA = 221;
1156         /** @hide */
1157         public static final int EID_EXTENSION_PRESENT = 255;
1158 
1159         // Extension IDs
1160         /** @hide */
1161         public static final int EID_EXT_HE_CAPABILITIES = 35;
1162         /** @hide */
1163         public static final int EID_EXT_HE_OPERATION = 36;
1164         /**
1165          * EHT Operation IE extension id: see IEEE 802.11be Specification section 9.4.2.1
1166          *
1167          * @hide
1168          */
1169         public static final int EID_EXT_EHT_OPERATION = 106;
1170         /**
1171          * Multi-Link IE extension id: see IEEE 802.11be Specification section 9.4.2.1
1172          *
1173          * @hide
1174          */
1175         public static final int EID_EXT_MULTI_LINK = 107;
1176         /**
1177          * EHT Capabilities IE extension id: see IEEE 802.11be Specification section 9.4.2.1
1178          *
1179          * @hide
1180          */
1181         public static final int EID_EXT_EHT_CAPABILITIES = 108;
1182 
1183         /** @hide */
1184         @UnsupportedAppUsage
1185         public int id;
1186         /** @hide */
1187         public int idExt;
1188 
1189         /** @hide */
1190         @UnsupportedAppUsage
1191         public byte[] bytes;
1192 
1193         /** @hide */
InformationElement()1194         public InformationElement() {
1195         }
1196 
1197         /**
1198          * Constructs InformationElements from beacon.
1199          *
1200          * @param id element id
1201          * @param idExt element id extension
1202          * @param bytes the body of the information element, may contain multiple elements
1203          */
InformationElement(int id, int idExt, @NonNull byte[] bytes)1204         public InformationElement(int id, int idExt, @NonNull byte[] bytes) {
1205             this.id = id;
1206             this.idExt = idExt;
1207             this.bytes = bytes.clone();
1208         }
1209 
InformationElement(@onNull InformationElement rhs)1210         public InformationElement(@NonNull InformationElement rhs) {
1211             this.id = rhs.id;
1212             this.idExt = rhs.idExt;
1213             this.bytes = rhs.bytes.clone();
1214         }
1215 
1216         /**
1217          * The element ID of the information element. Defined in the IEEE 802.11-2016 spec
1218          * Table 9-77.
1219          */
getId()1220         public int getId() {
1221             return id;
1222         }
1223 
1224         /**
1225          * The element ID Extension of the information element. Defined in the IEEE 802.11-2016 spec
1226          * Table 9-77.
1227          */
getIdExt()1228         public int getIdExt() {
1229             return idExt;
1230         }
1231 
1232         /**
1233          * Get the specific content of the information element.
1234          */
1235         @NonNull
getBytes()1236         public ByteBuffer getBytes() {
1237             return ByteBuffer.wrap(bytes).asReadOnlyBuffer();
1238         }
1239 
1240         /** Implement the Parcelable interface {@hide} */
describeContents()1241         public int describeContents() {
1242             return 0;
1243         }
1244 
1245         /** Implement the Parcelable interface {@hide} */
writeToParcel(Parcel dest, int flags)1246         public void writeToParcel(Parcel dest, int flags) {
1247             dest.writeInt(id);
1248             dest.writeInt(idExt);
1249             dest.writeByteArray(bytes);
1250         }
1251 
1252         /** Implement the Parcelable interface */
1253         public static final @NonNull Creator<InformationElement> CREATOR =
1254                 new Creator<InformationElement>() {
1255                     public InformationElement createFromParcel(Parcel in) {
1256                         InformationElement informationElement = new InformationElement();
1257                         informationElement.id = in.readInt();
1258                         informationElement.idExt = in.readInt();
1259                         informationElement.bytes = in.createByteArray();
1260                         return informationElement;
1261                     }
1262 
1263                     public InformationElement[] newArray(int size) {
1264                         return new InformationElement[size];
1265                     }
1266                 };
1267 
1268         @Override
equals(Object that)1269         public boolean equals(Object that) {
1270             if (this == that) return true;
1271 
1272             // Potential API behavior change, so don't change behavior on older devices.
1273             if (!SdkLevel.isAtLeastS()) return false;
1274 
1275             if (!(that instanceof InformationElement)) return false;
1276 
1277             InformationElement thatIE = (InformationElement) that;
1278             return id == thatIE.id
1279                     && idExt == thatIE.idExt
1280                     && Arrays.equals(bytes, thatIE.bytes);
1281         }
1282 
1283         @Override
hashCode()1284         public int hashCode() {
1285             // Potential API behavior change, so don't change behavior on older devices.
1286             if (!SdkLevel.isAtLeastS()) return System.identityHashCode(this);
1287 
1288             return Objects.hash(id, idExt, Arrays.hashCode(bytes));
1289         }
1290     }
1291 
1292     /**
1293      * information elements found in the beacon.
1294      * @hide
1295      */
1296     @UnsupportedAppUsage
1297     public InformationElement[] informationElements;
1298     /**
1299      * Get all information elements found in the beacon.
1300      */
1301     @NonNull
getInformationElements()1302     public List<InformationElement> getInformationElements() {
1303         return Collections.unmodifiableList(Arrays.asList(informationElements));
1304     }
1305 
1306     /**
1307      * Get all the security types supported by this ScanResult.
1308      * @return array of {@code WifiInfo#SECURITY_TYPE_*}.
1309      */
1310     @NonNull
getSecurityTypes()1311     public @WifiInfo.SecurityType int[] getSecurityTypes() {
1312         List<SecurityParams> params = ScanResultUtil.generateSecurityParamsListFromScanResult(this);
1313         int[] securityTypes = new int[params.size()];
1314         for (int i = 0; i < securityTypes.length; i++) {
1315             securityTypes[i] = WifiInfo.convertWifiConfigurationSecurityType(
1316                     params.get(i).getSecurityType());
1317         }
1318         return securityTypes;
1319     }
1320 
1321     /** ANQP response elements.
1322      * @hide
1323      */
1324     public AnqpInformationElement[] anqpElements;
1325 
1326     /**
1327      * Returns whether a WifiSsid represents a "hidden" SSID of all zero values.
1328      */
isHiddenSsid(@onNull WifiSsid wifiSsid)1329     private boolean isHiddenSsid(@NonNull WifiSsid wifiSsid) {
1330         for (byte b : wifiSsid.getBytes()) {
1331             if (b != 0) {
1332                 return false;
1333             }
1334         }
1335         return true;
1336     }
1337 
1338     /** {@hide} */
ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId, byte[] osuProviders, String caps, int level, int frequency, long tsf)1339     public ScanResult(WifiSsid wifiSsid, String BSSID, long hessid, int anqpDomainId,
1340             byte[] osuProviders, String caps, int level, int frequency, long tsf) {
1341         this.wifiSsid = wifiSsid;
1342         if (wifiSsid != null && isHiddenSsid(wifiSsid)) {
1343             // Retain the legacy behavior of setting SSID to "" if the SSID is all zero values.
1344             this.SSID = "";
1345         } else {
1346             final CharSequence utf8Ssid = (wifiSsid != null) ? wifiSsid.getUtf8Text() : null;
1347             this.SSID = (utf8Ssid != null) ? utf8Ssid.toString() : WifiManager.UNKNOWN_SSID;
1348         }
1349         this.BSSID = BSSID;
1350         this.hessid = hessid;
1351         this.anqpDomainId = anqpDomainId;
1352         if (osuProviders != null) {
1353             this.anqpElements = new AnqpInformationElement[1];
1354             this.anqpElements[0] =
1355                     new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID,
1356                             AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders);
1357         }
1358         this.capabilities = caps;
1359         this.level = level;
1360         this.frequency = frequency;
1361         this.timestamp = tsf;
1362         this.distanceCm = UNSPECIFIED;
1363         this.distanceSdCm = UNSPECIFIED;
1364         this.channelWidth = UNSPECIFIED;
1365         this.centerFreq0 = UNSPECIFIED;
1366         this.centerFreq1 = UNSPECIFIED;
1367         this.flags = 0;
1368         this.radioChainInfos = null;
1369         this.mApMldMacAddress = null;
1370     }
1371 
1372     /** {@hide} */
ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency, long tsf, int distCm, int distSdCm)1373     public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency,
1374             long tsf, int distCm, int distSdCm) {
1375         this.wifiSsid = wifiSsid;
1376         if (wifiSsid != null && isHiddenSsid(wifiSsid)) {
1377             // Retain the legacy behavior of setting SSID to "" if the SSID is all zero values.
1378             this.SSID = "";
1379         } else {
1380             final CharSequence utf8Ssid = (wifiSsid != null) ? wifiSsid.getUtf8Text() : null;
1381             this.SSID = (utf8Ssid != null) ? utf8Ssid.toString() : WifiManager.UNKNOWN_SSID;
1382         }
1383         this.BSSID = BSSID;
1384         this.capabilities = caps;
1385         this.level = level;
1386         this.frequency = frequency;
1387         this.timestamp = tsf;
1388         this.distanceCm = distCm;
1389         this.distanceSdCm = distSdCm;
1390         this.channelWidth = UNSPECIFIED;
1391         this.centerFreq0 = UNSPECIFIED;
1392         this.centerFreq1 = UNSPECIFIED;
1393         this.flags = 0;
1394         this.radioChainInfos = null;
1395         this.mApMldMacAddress = null;
1396     }
1397 
1398     /** {@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)1399     public ScanResult(String Ssid, String BSSID, long hessid, int anqpDomainId, String caps,
1400             int level, int frequency,
1401             long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1,
1402             boolean is80211McRTTResponder) {
1403         this.SSID = Ssid;
1404         this.BSSID = BSSID;
1405         this.hessid = hessid;
1406         this.anqpDomainId = anqpDomainId;
1407         this.capabilities = caps;
1408         this.level = level;
1409         this.frequency = frequency;
1410         this.timestamp = tsf;
1411         this.distanceCm = distCm;
1412         this.distanceSdCm = distSdCm;
1413         this.channelWidth = channelWidth;
1414         this.centerFreq0 = centerFreq0;
1415         this.centerFreq1 = centerFreq1;
1416         if (is80211McRTTResponder) {
1417             this.flags = FLAG_80211mc_RESPONDER;
1418         } else {
1419             this.flags = 0;
1420         }
1421         this.radioChainInfos = null;
1422         this.mApMldMacAddress = null;
1423     }
1424 
1425     /** {@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)1426     public ScanResult(WifiSsid wifiSsid, String Ssid, String BSSID, long hessid, int anqpDomainId,
1427                   String caps, int level,
1428                   int frequency, long tsf, int distCm, int distSdCm, int channelWidth,
1429                   int centerFreq0, int centerFreq1, boolean is80211McRTTResponder) {
1430         this(Ssid, BSSID, hessid, anqpDomainId, caps, level, frequency, tsf, distCm,
1431                 distSdCm, channelWidth, centerFreq0, centerFreq1, is80211McRTTResponder);
1432         this.wifiSsid = wifiSsid;
1433     }
1434 
1435     /** copy constructor */
ScanResult(@onNull ScanResult source)1436     public ScanResult(@NonNull ScanResult source) {
1437         if (source != null) {
1438             wifiSsid = source.wifiSsid;
1439             SSID = source.SSID;
1440             BSSID = source.BSSID;
1441             hessid = source.hessid;
1442             anqpDomainId = source.anqpDomainId;
1443             informationElements = source.informationElements;
1444             anqpElements = source.anqpElements;
1445             capabilities = source.capabilities;
1446             level = source.level;
1447             frequency = source.frequency;
1448             channelWidth = source.channelWidth;
1449             centerFreq0 = source.centerFreq0;
1450             centerFreq1 = source.centerFreq1;
1451             timestamp = source.timestamp;
1452             distanceCm = source.distanceCm;
1453             distanceSdCm = source.distanceSdCm;
1454             seen = source.seen;
1455             untrusted = source.untrusted;
1456             numUsage = source.numUsage;
1457             venueName = source.venueName;
1458             operatorFriendlyName = source.operatorFriendlyName;
1459             flags = source.flags;
1460             radioChainInfos = source.radioChainInfos;
1461             this.mWifiStandard = source.mWifiStandard;
1462             this.ifaceName = source.ifaceName;
1463             this.mApMldMacAddress = source.mApMldMacAddress;
1464             this.mApMloLinkId = source.mApMloLinkId;
1465             this.mAffiliatedMloLinks = source.mAffiliatedMloLinks != null
1466                     ? new ArrayList<>(source.mAffiliatedMloLinks) : Collections.emptyList();
1467         }
1468     }
1469 
1470     /** Construct an empty scan result. */
ScanResult()1471     public ScanResult() {
1472     }
1473 
1474     @Override
toString()1475     public String toString() {
1476         StringBuffer sb = new StringBuffer();
1477         String none = "<none>";
1478 
1479         sb.append("SSID: ")
1480                 .append(wifiSsid == null ? WifiManager.UNKNOWN_SSID : wifiSsid)
1481                 .append(", BSSID: ")
1482                 .append(BSSID == null ? none : BSSID)
1483                 .append(", capabilities: ")
1484                 .append(capabilities == null ? none : capabilities)
1485                 .append(", level: ")
1486                 .append(level)
1487                 .append(", frequency: ")
1488                 .append(frequency)
1489                 .append(", timestamp: ")
1490                 .append(timestamp);
1491         sb.append(", distance: ").append((distanceCm != UNSPECIFIED ? distanceCm : "?")).
1492                 append("(cm)");
1493         sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")).
1494                 append("(cm)");
1495 
1496         sb.append(", passpoint: ");
1497         sb.append(((flags & FLAG_PASSPOINT_NETWORK) != 0) ? "yes" : "no");
1498         sb.append(", ChannelBandwidth: ").append(channelWidth);
1499         sb.append(", centerFreq0: ").append(centerFreq0);
1500         sb.append(", centerFreq1: ").append(centerFreq1);
1501         sb.append(", standard: ").append(wifiStandardToString(mWifiStandard));
1502         sb.append(", 80211mcResponder: ");
1503         sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported");
1504         sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos));
1505         sb.append(", interface name: ").append(ifaceName);
1506 
1507         if (mApMldMacAddress != null) {
1508             sb.append(", MLO Info: ")
1509                     .append(" AP MLD MAC Address: ")
1510                     .append(mApMldMacAddress.toString())
1511                     .append(", AP MLO Link-Id: ")
1512                     .append((mApMloLinkId == MloLink.INVALID_MLO_LINK_ID)
1513                             ? "Unspecified" : mApMloLinkId)
1514                     .append(", AP MLO Affiliated Links: ").append(mAffiliatedMloLinks);
1515         }
1516 
1517         return sb.toString();
1518     }
1519 
1520     /** Implement the Parcelable interface {@hide} */
describeContents()1521     public int describeContents() {
1522         return 0;
1523     }
1524 
1525     /** Implement the Parcelable interface {@hide} */
writeToParcel(Parcel dest, int flags)1526     public void writeToParcel(Parcel dest, int flags) {
1527         if (wifiSsid != null) {
1528             dest.writeInt(1);
1529             wifiSsid.writeToParcel(dest, flags);
1530         } else {
1531             dest.writeInt(0);
1532         }
1533         dest.writeString(SSID);
1534         dest.writeString(BSSID);
1535         dest.writeLong(hessid);
1536         dest.writeInt(anqpDomainId);
1537         dest.writeString(capabilities);
1538         dest.writeInt(level);
1539         dest.writeInt(frequency);
1540         dest.writeLong(timestamp);
1541         dest.writeInt(distanceCm);
1542         dest.writeInt(distanceSdCm);
1543         dest.writeInt(channelWidth);
1544         dest.writeInt(centerFreq0);
1545         dest.writeInt(centerFreq1);
1546         dest.writeInt(mWifiStandard);
1547         dest.writeLong(seen);
1548         dest.writeInt(untrusted ? 1 : 0);
1549         dest.writeInt(numUsage);
1550         dest.writeString((venueName != null) ? venueName.toString() : "");
1551         dest.writeString((operatorFriendlyName != null) ? operatorFriendlyName.toString() : "");
1552         dest.writeLong(this.flags);
1553         dest.writeTypedArray(informationElements, flags);
1554 
1555         if (anqpLines != null) {
1556             dest.writeInt(anqpLines.size());
1557             for (int i = 0; i < anqpLines.size(); i++) {
1558                 dest.writeString(anqpLines.get(i));
1559             }
1560         }
1561         else {
1562             dest.writeInt(0);
1563         }
1564         if (anqpElements != null) {
1565             dest.writeInt(anqpElements.length);
1566             for (AnqpInformationElement element : anqpElements) {
1567                 dest.writeInt(element.getVendorId());
1568                 dest.writeInt(element.getElementId());
1569                 dest.writeInt(element.getPayload().length);
1570                 dest.writeByteArray(element.getPayload());
1571             }
1572         } else {
1573             dest.writeInt(0);
1574         }
1575 
1576         if (radioChainInfos != null) {
1577             dest.writeInt(radioChainInfos.length);
1578             for (int i = 0; i < radioChainInfos.length; i++) {
1579                 dest.writeInt(radioChainInfos[i].id);
1580                 dest.writeInt(radioChainInfos[i].level);
1581             }
1582         } else {
1583             dest.writeInt(0);
1584         }
1585         dest.writeString((ifaceName != null) ? ifaceName.toString() : "");
1586 
1587 
1588         // Add MLO related attributes
1589         dest.writeParcelable(mApMldMacAddress, flags);
1590         dest.writeInt(mApMloLinkId);
1591         dest.writeTypedList(mAffiliatedMloLinks);
1592     }
1593 
1594     /** Implement the Parcelable interface */
1595     public static final @NonNull Creator<ScanResult> CREATOR =
1596         new Creator<ScanResult>() {
1597             public ScanResult createFromParcel(Parcel in) {
1598                 WifiSsid wifiSsid = null;
1599                 if (in.readInt() == 1) {
1600                     wifiSsid = WifiSsid.CREATOR.createFromParcel(in);
1601                 }
1602                 ScanResult sr = new ScanResult(
1603                         wifiSsid,
1604                         in.readString(),                    /* SSID  */
1605                         in.readString(),                    /* BSSID */
1606                         in.readLong(),                      /* HESSID */
1607                         in.readInt(),                       /* ANQP Domain ID */
1608                         in.readString(),                    /* capabilities */
1609                         in.readInt(),                       /* level */
1610                         in.readInt(),                       /* frequency */
1611                         in.readLong(),                      /* timestamp */
1612                         in.readInt(),                       /* distanceCm */
1613                         in.readInt(),                       /* distanceSdCm */
1614                         in.readInt(),                       /* channelWidth */
1615                         in.readInt(),                       /* centerFreq0 */
1616                         in.readInt(),                       /* centerFreq1 */
1617                         false                               /* rtt responder,
1618                                                                fixed with flags below */
1619                 );
1620 
1621                 sr.mWifiStandard = in.readInt();
1622                 sr.seen = in.readLong();
1623                 sr.untrusted = in.readInt() != 0;
1624                 sr.numUsage = in.readInt();
1625                 sr.venueName = in.readString();
1626                 sr.operatorFriendlyName = in.readString();
1627                 sr.flags = in.readLong();
1628                 sr.informationElements = in.createTypedArray(InformationElement.CREATOR);
1629 
1630                 int n = in.readInt();
1631                 if (n != 0) {
1632                     sr.anqpLines = new ArrayList<String>();
1633                     for (int i = 0; i < n; i++) {
1634                         sr.anqpLines.add(in.readString());
1635                     }
1636                 }
1637                 n = in.readInt();
1638                 if (n != 0) {
1639                     sr.anqpElements = new AnqpInformationElement[n];
1640                     for (int i = 0; i < n; i++) {
1641                         int vendorId = in.readInt();
1642                         int elementId = in.readInt();
1643                         int len = in.readInt();
1644                         byte[] payload = new byte[len];
1645                         in.readByteArray(payload);
1646                         sr.anqpElements[i] =
1647                                 new AnqpInformationElement(vendorId, elementId, payload);
1648                     }
1649                 }
1650                 n = in.readInt();
1651                 if (n != 0) {
1652                     sr.radioChainInfos = new RadioChainInfo[n];
1653                     for (int i = 0; i < n; i++) {
1654                         sr.radioChainInfos[i] = new RadioChainInfo();
1655                         sr.radioChainInfos[i].id = in.readInt();
1656                         sr.radioChainInfos[i].level = in.readInt();
1657                     }
1658                 }
1659                 sr.ifaceName = in.readString();
1660 
1661 
1662                 // Read MLO related attributes
1663                 sr.mApMldMacAddress = in.readParcelable(MacAddress.class.getClassLoader());
1664                 sr.mApMloLinkId = in.readInt();
1665                 sr.mAffiliatedMloLinks = in.createTypedArrayList(MloLink.CREATOR);
1666 
1667                 return sr;
1668             }
1669 
1670             public ScanResult[] newArray(int size) {
1671                 return new ScanResult[size];
1672             }
1673         };
1674 }
1675