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 static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
20 
21 import android.Manifest;
22 import android.annotation.FlaggedApi;
23 import android.annotation.IntDef;
24 import android.annotation.IntRange;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.annotation.RequiresPermission;
28 import android.annotation.SystemApi;
29 import android.app.admin.DevicePolicyManager;
30 import android.compat.annotation.UnsupportedAppUsage;
31 import android.net.ConnectivityManager;
32 import android.net.ConnectivityManager.NetworkCallback;
33 import android.net.LinkProperties;
34 import android.net.MacAddress;
35 import android.net.Network;
36 import android.net.NetworkCapabilities;
37 import android.net.NetworkInfo.DetailedState;
38 import android.net.TransportInfo;
39 import android.os.Build;
40 import android.os.Parcel;
41 import android.os.Parcelable;
42 import android.os.SystemClock;
43 import android.telephony.SubscriptionManager;
44 import android.text.TextUtils;
45 import android.util.SparseArray;
46 
47 import androidx.annotation.RequiresApi;
48 
49 import com.android.modules.utils.build.SdkLevel;
50 import com.android.net.module.util.Inet4AddressUtils;
51 import com.android.wifi.flags.Flags;
52 
53 import java.lang.annotation.Retention;
54 import java.lang.annotation.RetentionPolicy;
55 import java.net.Inet4Address;
56 import java.net.InetAddress;
57 import java.net.UnknownHostException;
58 import java.util.ArrayList;
59 import java.util.Collections;
60 import java.util.Comparator;
61 import java.util.EnumMap;
62 import java.util.List;
63 import java.util.Locale;
64 import java.util.Objects;
65 
66 /**
67  * Describes the state of any Wi-Fi connection that is active or
68  * is in the process of being set up.
69  *
70  * In the connected state, access to location sensitive fields requires
71  * the same permissions as {@link WifiManager#getScanResults}. If such access is not allowed,
72  * {@link #getSSID} will return {@link WifiManager#UNKNOWN_SSID} and
73  * {@link #getBSSID} will return {@code "02:00:00:00:00:00"}.
74  * {@link #getApMldMacAddress()} will return null.
75  * {@link #getNetworkId()} will return {@code -1}.
76  * {@link #getPasspointFqdn()} will return null.
77  * {@link #getPasspointProviderFriendlyName()} will return null.
78  * {@link #getInformationElements()} will return null.
79  * {@link #getMacAddress()} will return {@code "02:00:00:00:00:00"}.
80  */
81 public class WifiInfo implements TransportInfo, Parcelable {
82     private static final String TAG = "WifiInfo";
83 
84     /**
85      * This is the map described in the Javadoc comment above. The positions
86      * of the elements of the array must correspond to the ordinal values
87      * of <code>DetailedState</code>.
88      */
89     private static final EnumMap<SupplicantState, DetailedState> stateMap =
90             new EnumMap<SupplicantState, DetailedState>(SupplicantState.class);
91 
92     /**
93      * Default MAC address reported to a client that does not have the
94      * android.permission.LOCAL_MAC_ADDRESS permission.
95      *
96      * @hide
97      */
98     @SystemApi
99     public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
100 
101     static {
stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED)102         stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED)103         stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.INACTIVE, DetailedState.IDLE)104         stateMap.put(SupplicantState.INACTIVE, DetailedState.IDLE);
stateMap.put(SupplicantState.SCANNING, DetailedState.SCANNING)105         stateMap.put(SupplicantState.SCANNING, DetailedState.SCANNING);
stateMap.put(SupplicantState.AUTHENTICATING, DetailedState.CONNECTING)106         stateMap.put(SupplicantState.AUTHENTICATING, DetailedState.CONNECTING);
stateMap.put(SupplicantState.ASSOCIATING, DetailedState.CONNECTING)107         stateMap.put(SupplicantState.ASSOCIATING, DetailedState.CONNECTING);
stateMap.put(SupplicantState.ASSOCIATED, DetailedState.CONNECTING)108         stateMap.put(SupplicantState.ASSOCIATED, DetailedState.CONNECTING);
stateMap.put(SupplicantState.FOUR_WAY_HANDSHAKE, DetailedState.AUTHENTICATING)109         stateMap.put(SupplicantState.FOUR_WAY_HANDSHAKE, DetailedState.AUTHENTICATING);
stateMap.put(SupplicantState.GROUP_HANDSHAKE, DetailedState.AUTHENTICATING)110         stateMap.put(SupplicantState.GROUP_HANDSHAKE, DetailedState.AUTHENTICATING);
stateMap.put(SupplicantState.COMPLETED, DetailedState.OBTAINING_IPADDR)111         stateMap.put(SupplicantState.COMPLETED, DetailedState.OBTAINING_IPADDR);
stateMap.put(SupplicantState.DORMANT, DetailedState.DISCONNECTED)112         stateMap.put(SupplicantState.DORMANT, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.UNINITIALIZED, DetailedState.IDLE)113         stateMap.put(SupplicantState.UNINITIALIZED, DetailedState.IDLE);
stateMap.put(SupplicantState.INVALID, DetailedState.FAILED)114         stateMap.put(SupplicantState.INVALID, DetailedState.FAILED);
115     }
116 
117     private SupplicantState mSupplicantState;
118     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
119     private String mBSSID;
120     @UnsupportedAppUsage
121     private WifiSsid mWifiSsid;
122     private boolean mIsHiddenSsid = false;
123     private int mNetworkId;
124     private int mSecurityType;
125 
126     /**
127      * The Multi-Link Device (MLD) MAC Address for the connected access point.
128      * Only applicable for Wi-Fi 7 access points, null otherwise.
129      * This will be set even if the STA is non-MLD
130      */
131     private MacAddress mApMldMacAddress;
132 
133     /**
134      * The Multi-Link Operation (MLO) link-id for the access point.
135      * Only applicable for Wi-Fi 7 access points.
136      */
137     private int mApMloLinkId;
138 
139     /** Maps link id to Affiliated MLO links. */
140     private SparseArray<MloLink> mAffiliatedMloLinksMap = new SparseArray<>();
141 
142     /**
143      * The Multi-Link Operation (MLO) affiliated Links.
144      * Only applicable for Wi-Fi 7 access points.
145      */
146     private List<MloLink> mAffiliatedMloLinks;
147 
148     /**
149      * Used to indicate that the RSSI is invalid, for example if no RSSI measurements are available
150      * yet.
151      * @hide
152      */
153     @SystemApi
154     public static final int INVALID_RSSI = -127;
155 
156     /** @hide **/
157     public static final int UNKNOWN_FREQUENCY = -1;
158 
159     /** @hide **/
160     public static final int MIN_RSSI = -126;
161 
162     /** @hide **/
163     public static final int MAX_RSSI = 200;
164 
165     /** Unknown security type. */
166     public static final int SECURITY_TYPE_UNKNOWN = -1;
167     /** Security type for an open network. */
168     public static final int SECURITY_TYPE_OPEN = 0;
169     /** Security type for a WEP network. */
170     public static final int SECURITY_TYPE_WEP = 1;
171     /** Security type for a PSK network. */
172     public static final int SECURITY_TYPE_PSK = 2;
173     /** Security type for an EAP network. */
174     public static final int SECURITY_TYPE_EAP = 3;
175     /** Security type for an SAE network. */
176     public static final int SECURITY_TYPE_SAE = 4;
177     /** Security type for a WPA3-Enterprise in 192-bit security network. */
178     public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT = 5;
179     /** Security type for an OWE network. */
180     public static final int SECURITY_TYPE_OWE = 6;
181     /** Security type for a WAPI PSK network. */
182     public static final int SECURITY_TYPE_WAPI_PSK = 7;
183     /** Security type for a WAPI Certificate network. */
184     public static final int SECURITY_TYPE_WAPI_CERT = 8;
185     /** Security type for a WPA3-Enterprise network. */
186     public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE = 9;
187     /** Security type for an OSEN network. */
188     public static final int SECURITY_TYPE_OSEN = 10;
189     /** Security type for a Passpoint R1/R2 network, where TKIP and WEP are not allowed. */
190     public static final int SECURITY_TYPE_PASSPOINT_R1_R2 = 11;
191     /**
192      * Security type for a Passpoint R3 network, where TKIP and WEP are not allowed,
193      * and PMF must be set to Required.
194      */
195     public static final int SECURITY_TYPE_PASSPOINT_R3 = 12;
196     /** Security type for Easy Connect (DPP) network */
197     public static final int SECURITY_TYPE_DPP = 13;
198 
199     /**
200      * Unknown security type that cannot be converted to
201      * DevicePolicyManager.WifiSecurity security type.
202      * @hide
203      */
204     public static final int DPM_SECURITY_TYPE_UNKNOWN = -1;
205 
206     /** @see #isPrimary() - No permission to access the field.  */
207     private static final int IS_PRIMARY_NO_PERMISSION = -1;
208     /** @see #isPrimary() - false */
209     private static final int IS_PRIMARY_FALSE = 0;
210     /** @see #isPrimary() - true */
211     private static final int IS_PRIMARY_TRUE = 1;
212     /** Tri state to store {@link #isPrimary()} field. */
213     /** @hide */
214     @Retention(RetentionPolicy.SOURCE)
215     @IntDef(prefix = { "IS_PRIMARY_" }, value = {
216             IS_PRIMARY_NO_PERMISSION, IS_PRIMARY_FALSE, IS_PRIMARY_TRUE
217     })
218     public @interface IsPrimaryValues {}
219 
220     /**
221      * Received Signal Strength Indicator
222      */
223     private int mRssi;
224     private long mLastRssiUpdateMillis;
225 
226     /**
227      * Wi-Fi standard for the connection
228      */
229     private @WifiAnnotations.WifiStandard int mWifiStandard;
230 
231     /**
232      * The unit in which links speeds are expressed.
233      */
234     public static final String LINK_SPEED_UNITS = "Mbps";
235     private int mLinkSpeed;
236 
237     /**
238      * Constant for unknown link speed.
239      */
240     public static final int LINK_SPEED_UNKNOWN = -1;
241 
242     /**
243      * Tx(transmit) Link speed in Mbps
244      */
245     private int mTxLinkSpeed;
246 
247     /**
248      * Max supported Tx(transmit) link speed in Mbps
249      */
250     private int mMaxSupportedTxLinkSpeed;
251 
252     /**
253      * Rx(receive) Link speed in Mbps
254      */
255     private int mRxLinkSpeed;
256 
257     /**
258      * Max supported Rx(receive) link speed in Mbps
259      */
260     private int mMaxSupportedRxLinkSpeed;
261 
262     /**
263      * Frequency in MHz
264      */
265     public static final String FREQUENCY_UNITS = "MHz";
266     private int mFrequency;
267 
268     @UnsupportedAppUsage
269     private InetAddress mIpAddress;
270     @UnsupportedAppUsage
271     private String mMacAddress = DEFAULT_MAC_ADDRESS;
272 
273     /**
274      * Whether the network is ephemeral or not.
275      */
276     private boolean mEphemeral;
277 
278     /**
279      * Whether the network is trusted or not.
280      */
281     private boolean mTrusted;
282 
283     /**
284      * Whether the network is restricted or not.
285      */
286     private boolean mRestricted;
287 
288     /**
289      * Whether the network is oem paid or not.
290      */
291     private boolean mOemPaid;
292 
293     /**
294      * Whether the network is oem private or not.
295      */
296     private boolean mOemPrivate;
297 
298     /**
299      * Whether the network is a carrier merged network.
300      */
301     private boolean mCarrierMerged;
302 
303     /**
304      * OSU (Online Sign Up) AP for Passpoint R2.
305      */
306     private boolean mOsuAp;
307 
308     /**
309      * Fully qualified domain name of a Passpoint configuration
310      */
311     private String mFqdn;
312 
313     /**
314      * Name of Passpoint credential provider
315      */
316     private String mProviderFriendlyName;
317 
318     /**
319      * If connected to a network suggestion or specifier, store the package name of the app,
320      * else null.
321      */
322     private String mRequestingPackageName;
323 
324     /**
325      * Identify which Telephony subscription provides this network.
326      */
327     private int mSubscriptionId;
328 
329     /**
330      * Running total count of lost (not ACKed) transmitted unicast data packets.
331      * @hide
332      */
333     public long txBad;
334     /**
335      * Running total count of transmitted unicast data retry packets.
336      * @hide
337      */
338     public long txRetries;
339     /**
340      * Running total count of successfully transmitted (ACKed) unicast data packets.
341      * @hide
342      */
343     public long txSuccess;
344     /**
345      * Running total count of received unicast data packets.
346      * @hide
347      */
348     public long rxSuccess;
349 
350     private double mLostTxPacketsPerSecond;
351 
352     /**
353      * TID-to-link mapping negotiation support by the AP.
354      */
355     private boolean mApTidToLinkMappingNegotiationSupported;
356 
357     /**
358      * Average rate of lost transmitted packets, in units of packets per second. In case of Multi
359      * Link Operation (MLO), returned value is the average rate of lost transmitted packets on all
360      * associated links.
361      *
362      * @hide
363      */
364     @SystemApi
getLostTxPacketsPerSecond()365     public double getLostTxPacketsPerSecond() {
366         return mLostTxPacketsPerSecond;
367     }
368 
369     /** @hide */
setLostTxPacketsPerSecond(double lostTxPacketsPerSecond)370     public void setLostTxPacketsPerSecond(double lostTxPacketsPerSecond) {
371         mLostTxPacketsPerSecond = lostTxPacketsPerSecond;
372     }
373 
374     private double mTxRetriedTxPacketsPerSecond;
375 
376     /**
377      * Average rate of transmitted retry packets, in units of packets per second. In case Multi Link
378      * Operation (MLO), the returned value is the average rate of transmitted retry packets on all
379      * associated links.
380      *
381      * @hide
382      */
383     @SystemApi
getRetriedTxPacketsPerSecond()384     public double getRetriedTxPacketsPerSecond() {
385         return mTxRetriedTxPacketsPerSecond;
386     }
387 
388     /** @hide */
setRetriedTxPacketsRate(double txRetriedTxPacketsPerSecond)389     public void setRetriedTxPacketsRate(double txRetriedTxPacketsPerSecond) {
390         mTxRetriedTxPacketsPerSecond = txRetriedTxPacketsPerSecond;
391     }
392 
393     private double mSuccessfulTxPacketsPerSecond;
394 
395     /**
396      * Average rate of successfully transmitted unicast packets, in units of packets per second. In
397      * case Multi Link Operation (MLO), returned value is the average rate of successfully
398      * transmitted unicast packets on all associated links.
399      *
400      * @hide
401      */
402     @SystemApi
getSuccessfulTxPacketsPerSecond()403     public double getSuccessfulTxPacketsPerSecond() {
404         return mSuccessfulTxPacketsPerSecond;
405     }
406 
407     /** @hide */
setSuccessfulTxPacketsPerSecond(double successfulTxPacketsPerSecond)408     public void setSuccessfulTxPacketsPerSecond(double successfulTxPacketsPerSecond) {
409         mSuccessfulTxPacketsPerSecond = successfulTxPacketsPerSecond;
410     }
411 
412     private double mSuccessfulRxPacketsPerSecond;
413 
414     /**
415      * Average rate of received unicast data packets, in units of packets per second. In case of
416      * Multi Link Operation (MLO), the returned value is the average rate of received unicast data
417      * packets on all associated links.
418      *
419      * @hide
420      */
421     @SystemApi
getSuccessfulRxPacketsPerSecond()422     public double getSuccessfulRxPacketsPerSecond() {
423         return mSuccessfulRxPacketsPerSecond;
424     }
425 
426     /** @hide */
setSuccessfulRxPacketsPerSecond(double successfulRxPacketsPerSecond)427     public void setSuccessfulRxPacketsPerSecond(double successfulRxPacketsPerSecond) {
428         mSuccessfulRxPacketsPerSecond = successfulRxPacketsPerSecond;
429     }
430 
431     /** @hide */
432     @UnsupportedAppUsage
433     public int score;
434 
435     /**
436      * The current Wifi score.
437      * NOTE: this value should only be used for debugging purposes. Do not rely on this value for
438      * any computations. The meaning of this value can and will change at any time without warning.
439      * @hide
440      */
441     @SystemApi
getScore()442     public int getScore() {
443         return score;
444     }
445 
446     /** @hide */
setScore(int score)447     public void setScore(int score) {
448         this.score = score;
449     }
450 
451     /** @hide */
452     private boolean mIsUsable = true;
453 
454     /** @hide */
isUsable()455     public boolean isUsable() {
456         return mIsUsable;
457     }
458 
459     /**
460      * This could be set to false by the external scorer when the network quality is bad.
461      * The wifi module could use this information in network selection.
462      * @hide
463      */
setUsable(boolean isUsable)464     public void setUsable(boolean isUsable) {
465         mIsUsable = isUsable;
466     }
467 
468     /**
469      * Flag indicating that AP has hinted that upstream connection is metered,
470      * and sensitive to heavy data transfers.
471      */
472     private boolean mMeteredHint;
473 
474     /**
475      * Passpoint unique key
476      */
477     private String mPasspointUniqueId;
478 
479     /**
480      * information elements found in the beacon of the connected bssid.
481      */
482     @Nullable
483     private List<ScanResult.InformationElement> mInformationElements;
484 
485     /**
486      * @see #isPrimary()
487      * The field is stored as an int since is a tristate internally -  true, false, no permission.
488      */
489     private @IsPrimaryValues int mIsPrimary;
490 
491     /**
492      * Key of the current network.
493      */
494     private String mNetworkKey;
495 
496     /** List of {@link OuiKeyedData} providing vendor-specific configuration data. */
497     private @NonNull List<OuiKeyedData> mVendorData;
498 
499     /** @hide */
500     @UnsupportedAppUsage
WifiInfo()501     public WifiInfo() {
502         mWifiSsid = null;
503         mBSSID = null;
504         mApMldMacAddress = null;
505         mApMloLinkId = 0;
506         mAffiliatedMloLinks = Collections.emptyList();
507         mNetworkId = -1;
508         mSupplicantState = SupplicantState.UNINITIALIZED;
509         mRssi = INVALID_RSSI;
510         mLinkSpeed = LINK_SPEED_UNKNOWN;
511         mFrequency = UNKNOWN_FREQUENCY;
512         mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
513         mSecurityType = -1;
514         mIsPrimary = IS_PRIMARY_FALSE;
515         mNetworkKey = null;
516         mApMloLinkId = MloLink.INVALID_MLO_LINK_ID;
517         mVendorData = Collections.emptyList();
518     }
519 
520     /** @hide */
reset()521     public void reset() {
522         setInetAddress(null);
523         setBSSID(null);
524         setSSID(null);
525         setHiddenSSID(false);
526         setNetworkId(-1);
527         setRssi(INVALID_RSSI);
528         setLinkSpeed(LINK_SPEED_UNKNOWN);
529         setTxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
530         setRxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
531         setMaxSupportedTxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
532         setMaxSupportedRxLinkSpeedMbps(LINK_SPEED_UNKNOWN);
533         setFrequency(-1);
534         setMeteredHint(false);
535         setEphemeral(false);
536         setTrusted(false);
537         setOemPaid(false);
538         setOemPrivate(false);
539         setCarrierMerged(false);
540         setOsuAp(false);
541         setRequestingPackageName(null);
542         setFQDN(null);
543         setProviderFriendlyName(null);
544         setPasspointUniqueId(null);
545         setSubscriptionId(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
546         setInformationElements(null);
547         setIsPrimary(false);
548         setRestricted(false);
549         txBad = 0;
550         txSuccess = 0;
551         rxSuccess = 0;
552         txRetries = 0;
553         mLostTxPacketsPerSecond = 0;
554         mSuccessfulTxPacketsPerSecond = 0;
555         mSuccessfulRxPacketsPerSecond = 0;
556         mTxRetriedTxPacketsPerSecond = 0;
557         score = 0;
558         mIsUsable = true;
559         mSecurityType = -1;
560         mNetworkKey = null;
561         resetMultiLinkInfo();
562         enableApTidToLinkMappingNegotiationSupport(false);
563         mVendorData = Collections.emptyList();
564     }
565 
566     /** @hide */
resetMultiLinkInfo()567     public void resetMultiLinkInfo() {
568         setApMldMacAddress(null);
569         mApMloLinkId = MloLink.INVALID_MLO_LINK_ID;
570         mAffiliatedMloLinks = Collections.emptyList();
571     }
572 
573     /**
574      * Copy constructor
575      * @hide
576      */
WifiInfo(WifiInfo source)577     public WifiInfo(WifiInfo source) {
578         this(source, NetworkCapabilities.REDACT_NONE);
579     }
580 
581     /**
582      * Copy constructor
583      * @hide
584      */
WifiInfo(WifiInfo source, long redactions)585     private WifiInfo(WifiInfo source, long redactions) {
586         if (source != null) {
587             mSupplicantState = source.mSupplicantState;
588             mBSSID = shouldRedactLocationSensitiveFields(redactions)
589                     ? DEFAULT_MAC_ADDRESS : source.mBSSID;
590             mApMldMacAddress = shouldRedactLocationSensitiveFields(redactions)
591                     ? null : source.mApMldMacAddress;
592             mApMloLinkId = source.mApMloLinkId;
593             if (source.mApMldMacAddress != null) {
594                 mAffiliatedMloLinks = new ArrayList<MloLink>();
595                 for (MloLink link : source.mAffiliatedMloLinks) {
596                     mAffiliatedMloLinks.add(new MloLink(link, redactions));
597                 }
598             } else {
599                 mAffiliatedMloLinks = Collections.emptyList();
600             }
601             mWifiSsid = shouldRedactLocationSensitiveFields(redactions)
602                     ? null : source.mWifiSsid;
603             mNetworkId = shouldRedactLocationSensitiveFields(redactions)
604                     ? INVALID_NETWORK_ID : source.mNetworkId;
605             mRssi = source.mRssi;
606             mLinkSpeed = source.mLinkSpeed;
607             mTxLinkSpeed = source.mTxLinkSpeed;
608             mRxLinkSpeed = source.mRxLinkSpeed;
609             mFrequency = source.mFrequency;
610             mIpAddress = source.mIpAddress;
611             mMacAddress = (shouldRedactLocalMacAddressFields(redactions)
612                     || shouldRedactLocationSensitiveFields(redactions))
613                             ? DEFAULT_MAC_ADDRESS : source.mMacAddress;
614             mMeteredHint = source.mMeteredHint;
615             mEphemeral = source.mEphemeral;
616             mTrusted = source.mTrusted;
617             mRestricted = source.mRestricted;
618             mOemPaid = source.mOemPaid;
619             mOemPrivate = source.mOemPrivate;
620             mCarrierMerged = source.mCarrierMerged;
621             mRequestingPackageName = shouldRedactNetworkSettingsFields(redactions) ? null
622                     : source.mRequestingPackageName;
623             mOsuAp = source.mOsuAp;
624             mFqdn = shouldRedactLocationSensitiveFields(redactions)
625                     ? null : source.mFqdn;
626             mProviderFriendlyName = shouldRedactLocationSensitiveFields(redactions)
627                     ? null : source.mProviderFriendlyName;
628             mSubscriptionId = source.mSubscriptionId;
629             txBad = source.txBad;
630             txRetries = source.txRetries;
631             txSuccess = source.txSuccess;
632             rxSuccess = source.rxSuccess;
633             mLostTxPacketsPerSecond = source.mLostTxPacketsPerSecond;
634             mTxRetriedTxPacketsPerSecond = source.mTxRetriedTxPacketsPerSecond;
635             mSuccessfulTxPacketsPerSecond = source.mSuccessfulTxPacketsPerSecond;
636             mSuccessfulRxPacketsPerSecond = source.mSuccessfulRxPacketsPerSecond;
637             score = source.score;
638             mIsUsable = source.mIsUsable;
639             mWifiStandard = source.mWifiStandard;
640             mMaxSupportedTxLinkSpeed = source.mMaxSupportedTxLinkSpeed;
641             mMaxSupportedRxLinkSpeed = source.mMaxSupportedRxLinkSpeed;
642             mPasspointUniqueId = shouldRedactLocationSensitiveFields(redactions)
643                     ? null : source.mPasspointUniqueId;
644             if (source.mInformationElements != null
645                     && !shouldRedactLocationSensitiveFields(redactions)) {
646                 mInformationElements = new ArrayList<>(source.mInformationElements);
647             }
648             mIsPrimary = shouldRedactNetworkSettingsFields(redactions)
649                     ? IS_PRIMARY_NO_PERMISSION : source.mIsPrimary;
650             mSecurityType = source.mSecurityType;
651             mNetworkKey = shouldRedactLocationSensitiveFields(redactions)
652                     ? null : source.mNetworkKey;
653             mApTidToLinkMappingNegotiationSupported =
654                     source.mApTidToLinkMappingNegotiationSupported;
655             mVendorData = new ArrayList<>(source.mVendorData);
656         }
657     }
658 
659     /** Builder for WifiInfo */
660     public static final class Builder {
661         private final WifiInfo mWifiInfo = new WifiInfo();
662 
663         /**
664          * Set the SSID, in the form of a raw byte array.
665          * @see WifiInfo#getSSID()
666          */
667         @NonNull
setSsid(@onNull byte[] ssid)668         public Builder setSsid(@NonNull byte[] ssid) {
669             mWifiInfo.setSSID(WifiSsid.fromBytes(ssid));
670             return this;
671         }
672 
673         /**
674          * Set the BSSID.
675          * @see WifiInfo#getBSSID()
676          */
677         @NonNull
setBssid(@onNull String bssid)678         public Builder setBssid(@NonNull String bssid) {
679             mWifiInfo.setBSSID(bssid);
680             return this;
681         }
682 
683         /**
684          * Set the AP MLD (Multi-Link Device) MAC Address.
685          * @see WifiInfo#getApMldMacAddress()
686          * @hide
687          */
688         @Nullable
setApMldMacAddress(@ullable MacAddress address)689         public Builder setApMldMacAddress(@Nullable MacAddress address) {
690             mWifiInfo.setApMldMacAddress(address);
691             return this;
692         }
693 
694         /**
695          * Set the access point Multi-Link Operation (MLO) link-id.
696          * @see WifiInfo#getApMloLinkId()
697          * @hide
698          */
setApMloLinkId(int linkId)699         public Builder setApMloLinkId(int linkId) {
700             mWifiInfo.setApMloLinkId(linkId);
701             return this;
702         }
703 
704         /**
705          * Set the Multi-Link Operation (MLO) affiliated Links.
706          * Only applicable for Wi-Fi 7 access points.
707          * @see WifiInfo#getAffiliatedMloLinks()
708          * @hide
709          */
setAffiliatedMloLinks(@onNull List<MloLink> links)710         public Builder setAffiliatedMloLinks(@NonNull List<MloLink> links) {
711             mWifiInfo.setAffiliatedMloLinks(links);
712             return this;
713         }
714 
715         /**
716          * Set the RSSI, in dBm.
717          * @see WifiInfo#getRssi()
718          */
719         @NonNull
setRssi(int rssi)720         public Builder setRssi(int rssi) {
721             mWifiInfo.setRssi(rssi);
722             return this;
723         }
724 
725         /**
726          * Set the network ID.
727          * @see WifiInfo#getNetworkId()
728          */
729         @NonNull
setNetworkId(int networkId)730         public Builder setNetworkId(int networkId) {
731             mWifiInfo.setNetworkId(networkId);
732             return this;
733         }
734 
735         /**
736          * Set the subscription ID.
737          * @see WifiInfo#getSubscriptionId()
738          */
739         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
740         @NonNull
setSubscriptionId(int subId)741         public Builder setSubscriptionId(int subId) {
742             mWifiInfo.setSubscriptionId(subId);
743             return this;
744         }
745 
746         /**
747          * Set the current security type
748          * @see WifiInfo#getCurrentSecurityType()
749          */
750         @NonNull
setCurrentSecurityType(@ifiConfiguration.SecurityType int securityType)751         public Builder setCurrentSecurityType(@WifiConfiguration.SecurityType int securityType) {
752             mWifiInfo.setCurrentSecurityType(securityType);
753             return this;
754         }
755 
756         /**
757          * Enable or Disable Peer TID-To-Link Mapping Negotiation Capability.
758          * See {@link WifiInfo#isApTidToLinkMappingNegotiationSupported()}
759          * @hide
760          */
761         @NonNull
enableApTidToLinkMappingNegotiationSupport(boolean enable)762         public Builder enableApTidToLinkMappingNegotiationSupport(boolean enable) {
763             mWifiInfo.enableApTidToLinkMappingNegotiationSupport(enable);
764             return this;
765         }
766 
767         /**
768          * Build a WifiInfo object.
769          */
770         @NonNull
build()771         public WifiInfo build() {
772             return new WifiInfo(mWifiInfo);
773         }
774     }
775 
776     /** @hide */
setSSID(WifiSsid wifiSsid)777     public void setSSID(WifiSsid wifiSsid) {
778         mWifiSsid = wifiSsid;
779     }
780 
781     /**
782      * Returns the service set identifier (SSID) of the current 802.11 network.
783      * <p>
784      * If the SSID can be decoded as UTF-8, it will be returned surrounded by double
785      * quotation marks. Otherwise, it is returned as a string of hex digits.
786      * The SSID may be {@link WifiManager#UNKNOWN_SSID}, if there is no network currently connected
787      * or if the caller has insufficient permissions to access the SSID.
788      * </p>
789      * <p>
790      * Prior to {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method
791      * always returned the SSID with no quotes around it.
792      * </p>
793      *
794      * @return the SSID.
795      */
getSSID()796     public String getSSID() {
797         if (mWifiSsid != null) {
798             String ssidString = mWifiSsid.toString();
799             if (!TextUtils.isEmpty(ssidString)) {
800                 return ssidString;
801             }
802         }
803         return WifiManager.UNKNOWN_SSID;
804     }
805 
806     /** @hide */
807     @UnsupportedAppUsage
getWifiSsid()808     public WifiSsid getWifiSsid() {
809         return mWifiSsid;
810     }
811 
812     /** @hide */
813     @UnsupportedAppUsage
setBSSID(String BSSID)814     public void setBSSID(String BSSID) {
815         mBSSID = BSSID;
816     }
817 
818     /**
819      * Set the access point Multi-Link Device (MLD) MAC Address.
820      * @hide
821      */
setApMldMacAddress(@ullable MacAddress address)822     public void setApMldMacAddress(@Nullable MacAddress address) {
823         mApMldMacAddress = address;
824     }
825 
826     /**
827      * Set the access point Multi-Link Operation (MLO) link-id
828      * @hide
829      */
setApMloLinkId(int linkId)830     public void setApMloLinkId(int linkId) {
831         mApMloLinkId = linkId;
832     }
833 
mapAffiliatedMloLinks()834     private void mapAffiliatedMloLinks() {
835         mAffiliatedMloLinksMap.clear();
836         for (MloLink link : mAffiliatedMloLinks) {
837             mAffiliatedMloLinksMap.put(link.getLinkId(), link);
838         }
839     }
840 
841     /**
842      * Set the Multi-Link Operation (MLO) affiliated Links.
843      * Only applicable for Wi-Fi 7 access points.
844      *
845      * @hide
846      */
setAffiliatedMloLinks(@onNull List<MloLink> links)847     public void setAffiliatedMloLinks(@NonNull List<MloLink> links) {
848         mAffiliatedMloLinks = new ArrayList<MloLink>(links);
849         mapAffiliatedMloLinks();
850     }
851 
852     /**
853      * Update the MLO link STA MAC Address
854      *
855      * @param linkId for the link to be updated.
856      * @param macAddress value to be set in the link.
857      *
858      * @return true on success, false on failure
859      *
860      * @hide
861      */
updateMloLinkStaAddress(int linkId, MacAddress macAddress)862     public boolean updateMloLinkStaAddress(int linkId, MacAddress macAddress) {
863         for (MloLink link : mAffiliatedMloLinks) {
864             if (link.getLinkId() == linkId) {
865                 link.setStaMacAddress(macAddress);
866                 return true;
867             }
868         }
869         return false;
870     }
871 
872     /**
873      * Update the MLO link State
874      *
875      * @param linkId for the link to be updated.
876      * @param state value to be set in the link as one of {@link MloLink.MloLinkState}
877      *
878      * @return true on success, false on failure
879      *
880      * @hide
881      */
updateMloLinkState(int linkId, @MloLink.MloLinkState int state)882     public boolean updateMloLinkState(int linkId, @MloLink.MloLinkState int state) {
883         if (!MloLink.isValidState(state)) {
884             return false;
885         }
886 
887         for (MloLink link : mAffiliatedMloLinks) {
888             if (link.getLinkId() == linkId) {
889                 link.setState(state);
890                 return true;
891             }
892         }
893         return false;
894     }
895 
896     /**
897      * Return the basic service set identifier (BSSID) of the current access point. In case of
898      * Multi Link Operation (MLO), the BSSID corresponds to the BSSID of the link used for
899      * association.
900      * <p>
901      * The BSSID may be
902      * <lt>{@code null}, if there is no network currently connected.</lt>
903      * <lt>{@code "02:00:00:00:00:00"}, if the caller has insufficient permissions to access the
904      * BSSID.<lt>
905      * </p>
906      *
907      * @return the BSSID, in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX}
908      */
getBSSID()909     public String getBSSID() {
910         return mBSSID;
911     }
912 
913     /**
914      * Return the Multi-Link Device (MLD) MAC Address for the connected access point.
915      * <p>
916      * The returned MLD MAC Address will be {@code null} in the following cases:
917      * <lt>There is no network currently connected</lt>
918      * <lt>The connected access point is not an MLD access point,
919      * i.e. {@link #getWifiStandard()} returns {@link ScanResult#WIFI_STANDARD_11BE}.</lt>
920      * <lt>The caller has insufficient permissions to access the access point MLD MAC Address.<lt>
921      * </p>
922      *
923      * @return the MLD Mac address
924      */
925     @Nullable
getApMldMacAddress()926     public MacAddress getApMldMacAddress() {
927         return mApMldMacAddress;
928     }
929 
930     /**
931      * Return the access point Multi-Link Operation (MLO) link-id for Wi-Fi 7 access points.
932      * i.e. {@link #getWifiStandard()} returns {@link ScanResult#WIFI_STANDARD_11BE},
933      * otherwise return {@link MloLink#INVALID_MLO_LINK_ID}.
934      *
935      * Valid values are 0-15 as described in IEEE 802.11be Specification, section 9.4.2.295b.2.
936      *
937      * @return {@link MloLink#INVALID_MLO_LINK_ID} or a valid value (0-15).
938      */
939     @IntRange(from = MloLink.INVALID_MLO_LINK_ID, to = MloLink.MAX_MLO_LINK_ID)
getApMloLinkId()940     public int getApMloLinkId() {
941         return mApMloLinkId;
942     }
943 
944     /**
945      * Return the Multi-Link Operation (MLO) affiliated Links for Wi-Fi 7 access points.
946      * i.e. when {@link #getWifiStandard()} returns {@link ScanResult#WIFI_STANDARD_11BE}.
947      *
948      * Affiliated links are the links supported by the Access Point Multi Link Device (AP MLD). The
949      * Station Multi Link Device (STA MLD) gathers affiliated link information from scan results.
950      * Depending on Station's capability, it associates to all or a subset of affiliated links.
951      * <p><b>Note:</b>{@link #getAssociatedMloLinks()} returns associated links.
952      *
953      * @return List of affiliated MLO links, or an empty list if access point is not Wi-Fi 7
954      */
955     @NonNull
getAffiliatedMloLinks()956     public List<MloLink> getAffiliatedMloLinks() {
957         return new ArrayList<MloLink>(mAffiliatedMloLinks);
958     }
959 
960     /** @hide */
getAffiliatedMloLink(int linkId)961     public MloLink getAffiliatedMloLink(int linkId) {
962         return mAffiliatedMloLinksMap.get(linkId);
963     }
964 
965     /**
966      * Return the associated Multi-Link Operation (MLO) Links for Wi-Fi 7 access points.
967      * i.e. when {@link #getWifiStandard()} returns {@link ScanResult#WIFI_STANDARD_11BE}.
968      *
969      * Affiliated links are the links supported by the Access Point Multi Link Device (AP MLD). The
970      * Station Multi Link Device (STA MLD) gathers affiliated link information from scan results.
971      * Depending on Station's capability, it associates to all or a subset of affiliated links.
972      * <p><b>Note:</b>{@link #getAffiliatedMloLinks()} returns affiliated links.
973      *
974      * @return List of associated MLO links, or an empty list if access point is not a multi-link
975      * device.
976      */
977     @NonNull
getAssociatedMloLinks()978     public List<MloLink> getAssociatedMloLinks() {
979         ArrayList associatedMloLinks = new ArrayList<MloLink>();
980         for (MloLink link : getAffiliatedMloLinks()) {
981             if (link.getState() == MloLink.MLO_LINK_STATE_IDLE
982                     || link.getState() == MloLink.MLO_LINK_STATE_ACTIVE) {
983                 associatedMloLinks.add(link);
984             }
985         }
986         return associatedMloLinks;
987     }
988 
989     /**
990      * Returns the received signal strength indicator of the current 802.11 network, in dBm. In
991      * case of Multi Link Operation (MLO), returned RSSI is the highest of all associated links.
992      * <p>
993      * Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
994      * an absolute signal level which can be displayed to a user.
995      * </p>
996      *
997      * @return the RSSI.
998      */
getRssi()999     public int getRssi() {
1000         return mRssi;
1001     }
1002 
1003     /** @hide */
1004     @UnsupportedAppUsage
setRssi(int rssi)1005     public void setRssi(int rssi) {
1006         if (rssi < INVALID_RSSI)
1007             rssi = INVALID_RSSI;
1008         if (rssi > MAX_RSSI)
1009             rssi = MAX_RSSI;
1010         mRssi = rssi;
1011         mLastRssiUpdateMillis = SystemClock.elapsedRealtime();
1012     }
1013 
1014     /**
1015      * @hide
1016      */
getLastRssiUpdateMillis()1017     public long getLastRssiUpdateMillis() {
1018         return mLastRssiUpdateMillis;
1019     }
1020 
1021     /**
1022      * Sets the Wi-Fi standard
1023      * @hide
1024      */
setWifiStandard(@ifiAnnotations.WifiStandard int wifiStandard)1025     public void setWifiStandard(@WifiAnnotations.WifiStandard int wifiStandard) {
1026         mWifiStandard = wifiStandard;
1027     }
1028 
1029     /**
1030      * Get connection Wi-Fi standard
1031      * @return the connection Wi-Fi standard
1032      */
getWifiStandard()1033     public @WifiAnnotations.WifiStandard int getWifiStandard() {
1034         return mWifiStandard;
1035     }
1036 
1037     /**
1038      * Returns the current link speed in {@link #LINK_SPEED_UNITS}. In case of Multi Link Operation
1039      * (MLO), returned value is the current link speed of the associated link with the highest RSSI.
1040      *
1041      * @return the link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
1042      * @see #LINK_SPEED_UNITS
1043      * @see #LINK_SPEED_UNKNOWN
1044      */
getLinkSpeed()1045     public int getLinkSpeed() {
1046         return mLinkSpeed;
1047     }
1048 
1049     /** @hide */
1050     @UnsupportedAppUsage
setLinkSpeed(int linkSpeed)1051     public void setLinkSpeed(int linkSpeed) {
1052         mLinkSpeed = linkSpeed;
1053     }
1054 
1055     /**
1056      * Returns the current transmit link speed in Mbps. In case of Multi Link Operation (MLO),
1057      * returned value is the current transmit link speed of the associated link with the highest
1058      * RSSI.
1059      *
1060      * @return the Tx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
1061      * @see #LINK_SPEED_UNKNOWN
1062      */
1063     @IntRange(from = -1)
getTxLinkSpeedMbps()1064     public int getTxLinkSpeedMbps() {
1065         return mTxLinkSpeed;
1066     }
1067 
1068     /**
1069      * Returns the maximum supported transmit link speed in Mbps
1070      * @return the max supported tx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is
1071      * unknown. @see #LINK_SPEED_UNKNOWN
1072      */
getMaxSupportedTxLinkSpeedMbps()1073     public int getMaxSupportedTxLinkSpeedMbps() {
1074         return mMaxSupportedTxLinkSpeed;
1075     }
1076 
1077     /**
1078      * Update the last transmitted packet bit rate in Mbps.
1079      * @hide
1080      */
setTxLinkSpeedMbps(int txLinkSpeed)1081     public void setTxLinkSpeedMbps(int txLinkSpeed) {
1082         mTxLinkSpeed = txLinkSpeed;
1083     }
1084 
1085     /**
1086      * Set the maximum supported transmit link speed in Mbps
1087      * @hide
1088      */
setMaxSupportedTxLinkSpeedMbps(int maxSupportedTxLinkSpeed)1089     public void setMaxSupportedTxLinkSpeedMbps(int maxSupportedTxLinkSpeed) {
1090         mMaxSupportedTxLinkSpeed = maxSupportedTxLinkSpeed;
1091     }
1092 
1093     /**
1094      * Returns the current receive link speed in Mbps. In case of Multi Link Operation (MLO),
1095      * returned value is the receive link speed of the associated link with the highest RSSI.
1096      *
1097      * @return the Rx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is unknown.
1098      * @see #LINK_SPEED_UNKNOWN
1099      */
1100     @IntRange(from = -1)
getRxLinkSpeedMbps()1101     public int getRxLinkSpeedMbps() {
1102         return mRxLinkSpeed;
1103     }
1104 
1105     /**
1106      * Returns the maximum supported receive link speed in Mbps
1107      * @return the max supported Rx link speed or {@link #LINK_SPEED_UNKNOWN} if link speed is
1108      * unknown. @see #LINK_SPEED_UNKNOWN
1109      */
getMaxSupportedRxLinkSpeedMbps()1110     public int getMaxSupportedRxLinkSpeedMbps() {
1111         return mMaxSupportedRxLinkSpeed;
1112     }
1113 
1114     /**
1115      * Update the last received packet bit rate in Mbps.
1116      * @hide
1117      */
setRxLinkSpeedMbps(int rxLinkSpeed)1118     public void setRxLinkSpeedMbps(int rxLinkSpeed) {
1119         mRxLinkSpeed = rxLinkSpeed;
1120     }
1121 
1122     /**
1123      * Set the maximum supported receive link speed in Mbps
1124      * @hide
1125      */
setMaxSupportedRxLinkSpeedMbps(int maxSupportedRxLinkSpeed)1126     public void setMaxSupportedRxLinkSpeedMbps(int maxSupportedRxLinkSpeed) {
1127         mMaxSupportedRxLinkSpeed = maxSupportedRxLinkSpeed;
1128     }
1129 
1130     /**
1131      * Returns the current frequency in {@link #FREQUENCY_UNITS}. In case of Multi Link Operation
1132      * (MLO), returned value is the frequency of the associated link with the highest RSSI.
1133      *
1134      * @return the frequency.
1135      * @see #FREQUENCY_UNITS
1136      */
getFrequency()1137     public int getFrequency() {
1138         return mFrequency;
1139     }
1140 
1141     /** @hide */
setFrequency(int frequency)1142     public void setFrequency(int frequency) {
1143         this.mFrequency = frequency;
1144     }
1145 
1146     /**
1147      * @hide
1148      */
is24GHz()1149     public boolean is24GHz() {
1150         return ScanResult.is24GHz(mFrequency);
1151     }
1152 
1153     /**
1154      * @hide
1155      */
1156     @UnsupportedAppUsage
is5GHz()1157     public boolean is5GHz() {
1158         return ScanResult.is5GHz(mFrequency);
1159     }
1160 
1161     /**
1162      * @hide
1163      */
is6GHz()1164     public boolean is6GHz() {
1165         return ScanResult.is6GHz(mFrequency);
1166     }
1167 
1168     /**
1169      * Record the MAC address of the WLAN interface
1170      * @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form
1171      * @hide
1172      */
1173     @UnsupportedAppUsage
setMacAddress(String macAddress)1174     public void setMacAddress(String macAddress) {
1175         this.mMacAddress = macAddress;
1176     }
1177 
1178     /**
1179      * Returns the MAC address used for this connection. In case of Multi Link Operation (MLO),
1180      * returned value is the Station MLD MAC address.
1181      *
1182      * @return MAC address of the connection or {@code "02:00:00:00:00:00"} if the caller has
1183      * insufficient permission.
1184      *
1185      * Requires {@code android.Manifest.permission#LOCAL_MAC_ADDRESS} and
1186      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
1187      */
getMacAddress()1188     public String getMacAddress() {
1189         return mMacAddress;
1190     }
1191 
1192     /**
1193      * @return true if {@link #getMacAddress()} has a real MAC address.
1194      *
1195      * @hide
1196      */
hasRealMacAddress()1197     public boolean hasRealMacAddress() {
1198         return mMacAddress != null && !DEFAULT_MAC_ADDRESS.equals(mMacAddress);
1199     }
1200 
1201     /**
1202      * Indicates if we've dynamically detected this active network connection as
1203      * being metered.
1204      *
1205      * @see WifiConfiguration#isMetered(WifiConfiguration, WifiInfo)
1206      * @hide
1207      */
setMeteredHint(boolean meteredHint)1208     public void setMeteredHint(boolean meteredHint) {
1209         mMeteredHint = meteredHint;
1210     }
1211 
1212     /** @hide */
1213     @UnsupportedAppUsage
getMeteredHint()1214     public boolean getMeteredHint() {
1215         return mMeteredHint;
1216     }
1217 
1218     /** @hide */
setEphemeral(boolean ephemeral)1219     public void setEphemeral(boolean ephemeral) {
1220         mEphemeral = ephemeral;
1221     }
1222 
1223     /**
1224      * Returns true if the current Wifi network is ephemeral, false otherwise.
1225      * An ephemeral network is a network that is temporary and not persisted in the system.
1226      * Ephemeral networks cannot be forgotten, only disabled with
1227      * {@link WifiManager#disableEphemeralNetwork(String)}.
1228      *
1229      * @hide
1230      */
1231     @SystemApi
isEphemeral()1232     public boolean isEphemeral() {
1233         return mEphemeral;
1234     }
1235 
1236     /** @hide */
setTrusted(boolean trusted)1237     public void setTrusted(boolean trusted) {
1238         mTrusted = trusted;
1239     }
1240 
1241     /**
1242      * Returns true if the current Wifi network is a trusted network, false otherwise.
1243      * @see WifiNetworkSuggestion.Builder#setUntrusted(boolean).
1244      * @hide
1245      */
1246     @SystemApi
isTrusted()1247     public boolean isTrusted() {
1248         return mTrusted;
1249     }
1250 
1251     /** @hide */
setRestricted(boolean restricted)1252     public void setRestricted(boolean restricted) {
1253         mRestricted = restricted;
1254     }
1255 
1256     /**
1257      * Returns true if the current Wifi network is a restricted network, false otherwise.
1258      * A restricted network has its {@link NetworkCapabilities#NET_CAPABILITY_NOT_RESTRICTED}
1259      * capability removed.
1260      * @see WifiNetworkSuggestion.Builder#setRestricted(boolean).
1261      */
isRestricted()1262     public boolean isRestricted() {
1263         return mRestricted;
1264     }
1265 
1266     /** @hide */
setOemPaid(boolean oemPaid)1267     public void setOemPaid(boolean oemPaid) {
1268         mOemPaid = oemPaid;
1269     }
1270 
1271     /**
1272      * Returns true if the current Wifi network is an oem paid network, false otherwise.
1273      * @see WifiNetworkSuggestion.Builder#setOemPaid(boolean).
1274      * @hide
1275      */
1276     @RequiresApi(Build.VERSION_CODES.S)
1277     @SystemApi
isOemPaid()1278     public boolean isOemPaid() {
1279         if (!SdkLevel.isAtLeastS()) {
1280             throw new UnsupportedOperationException();
1281         }
1282         return mOemPaid;
1283     }
1284 
1285     /** @hide */
setOemPrivate(boolean oemPrivate)1286     public void setOemPrivate(boolean oemPrivate) {
1287         mOemPrivate = oemPrivate;
1288     }
1289 
1290     /**
1291      * Returns true if the current Wifi network is an oem private network, false otherwise.
1292      * @see WifiNetworkSuggestion.Builder#setOemPrivate(boolean).
1293      * @hide
1294      */
1295     @RequiresApi(Build.VERSION_CODES.S)
1296     @SystemApi
isOemPrivate()1297     public boolean isOemPrivate() {
1298         if (!SdkLevel.isAtLeastS()) {
1299             throw new UnsupportedOperationException();
1300         }
1301         return mOemPrivate;
1302     }
1303 
1304     /**
1305      * @hide
1306      */
setCarrierMerged(boolean carrierMerged)1307     public void setCarrierMerged(boolean carrierMerged) {
1308         mCarrierMerged = carrierMerged;
1309     }
1310 
1311     /**
1312      * Returns true if the current Wifi network is a carrier merged network, false otherwise.
1313      * @see WifiNetworkSuggestion.Builder#setCarrierMerged(boolean).
1314      * @hide
1315      */
1316     @SystemApi
1317     @RequiresApi(Build.VERSION_CODES.S)
isCarrierMerged()1318     public boolean isCarrierMerged() {
1319         if (!SdkLevel.isAtLeastS()) {
1320             throw new UnsupportedOperationException();
1321         }
1322         return mCarrierMerged;
1323     }
1324 
1325 
1326     /** @hide */
setOsuAp(boolean osuAp)1327     public void setOsuAp(boolean osuAp) {
1328         mOsuAp = osuAp;
1329     }
1330 
1331     /** @hide */
1332     @SystemApi
isOsuAp()1333     public boolean isOsuAp() {
1334         return mOsuAp;
1335     }
1336 
1337     /** @hide */
1338     @SystemApi
isPasspointAp()1339     public boolean isPasspointAp() {
1340         return mFqdn != null && mProviderFriendlyName != null;
1341     }
1342 
1343     /** @hide */
setFQDN(@ullable String fqdn)1344     public void setFQDN(@Nullable String fqdn) {
1345         mFqdn = fqdn;
1346     }
1347 
1348     /**
1349      * Returns the Fully Qualified Domain Name of the network if it is a Passpoint network.
1350      * <p>
1351      * The FQDN may be
1352      * <lt>{@code null} if no network currently connected, currently connected network is not
1353      * passpoint network or the caller has insufficient permissions to access the FQDN.</lt>
1354      * </p>
1355      */
getPasspointFqdn()1356     public @Nullable String getPasspointFqdn() {
1357         return mFqdn;
1358     }
1359 
1360     /** @hide */
setProviderFriendlyName(@ullable String providerFriendlyName)1361     public void setProviderFriendlyName(@Nullable String providerFriendlyName) {
1362         mProviderFriendlyName = providerFriendlyName;
1363     }
1364 
1365     /**
1366      * Returns the Provider Friendly Name of the network if it is a Passpoint network.
1367      * <p>
1368      * The Provider Friendly Name may be
1369      * <lt>{@code null} if no network currently connected, currently connected network is not
1370      * passpoint network or the caller has insufficient permissions to access the Provider Friendly
1371      * Name. </lt>
1372      * </p>
1373      */
getPasspointProviderFriendlyName()1374     public @Nullable String getPasspointProviderFriendlyName() {
1375         return mProviderFriendlyName;
1376     }
1377 
1378     /** @hide */
setRequestingPackageName(@ullable String packageName)1379     public void setRequestingPackageName(@Nullable String packageName) {
1380         mRequestingPackageName = packageName;
1381     }
1382 
1383     /**
1384      * If this network was created in response to an app request (e.g. through Network Suggestion
1385      * or Network Specifier), return the package name of the app that made the request.
1386      * Null otherwise.
1387      * @hide
1388      */
1389     @SystemApi
getRequestingPackageName()1390     public @Nullable String getRequestingPackageName() {
1391         return mRequestingPackageName;
1392     }
1393 
1394     /** @hide */
setSubscriptionId(int subId)1395     public void setSubscriptionId(int subId) {
1396         mSubscriptionId = subId;
1397     }
1398 
1399     /**
1400      * If this network is provisioned by a carrier, returns subscription Id corresponding to the
1401      * associated SIM on the device. If this network is not provisioned by a carrier, returns
1402      * {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID}
1403      *
1404      * @see WifiNetworkSuggestion.Builder#setSubscriptionId(int)
1405      * @see android.telephony.SubscriptionInfo#getSubscriptionId()
1406      */
1407     @RequiresApi(Build.VERSION_CODES.S)
getSubscriptionId()1408     public int getSubscriptionId() {
1409         if (!SdkLevel.isAtLeastS()) {
1410             throw new UnsupportedOperationException();
1411         }
1412         return mSubscriptionId;
1413     }
1414 
1415 
1416     /** @hide */
1417     @UnsupportedAppUsage
setNetworkId(int id)1418     public void setNetworkId(int id) {
1419         mNetworkId = id;
1420     }
1421 
1422     /**
1423      * Each configured network has a unique small integer ID, used to identify
1424      * the network. This method returns the ID for the currently connected network.
1425      * <p>
1426      * The networkId may be {@code -1} if there is no currently connected network or if the caller
1427      * has insufficient permissions to access the network ID.
1428      * </p>
1429      *
1430      * @return the network ID.
1431      */
getNetworkId()1432     public int getNetworkId() {
1433         return mNetworkId;
1434     }
1435 
1436     /**
1437      * Return the detailed state of the supplicant's negotiation with an
1438      * access point, in the form of a {@link SupplicantState SupplicantState} object.
1439      * @return the current {@link SupplicantState SupplicantState}
1440      */
getSupplicantState()1441     public SupplicantState getSupplicantState() {
1442         return mSupplicantState;
1443     }
1444 
1445     /** @hide */
1446     @UnsupportedAppUsage
setSupplicantState(SupplicantState state)1447     public void setSupplicantState(SupplicantState state) {
1448         mSupplicantState = state;
1449     }
1450 
1451     /** @hide */
setInetAddress(InetAddress address)1452     public void setInetAddress(InetAddress address) {
1453         mIpAddress = address;
1454     }
1455 
1456     /**
1457      * @deprecated Use the methods on {@link android.net.LinkProperties} which can be obtained
1458      * either via {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)} or
1459      * {@link ConnectivityManager#getLinkProperties(Network)}.
1460      */
1461     @Deprecated
getIpAddress()1462     public int getIpAddress() {
1463         int result = 0;
1464         if (mIpAddress instanceof Inet4Address) {
1465             result = Inet4AddressUtils.inet4AddressToIntHTL((Inet4Address) mIpAddress);
1466         }
1467         return result;
1468     }
1469 
1470     /**
1471      * @return {@code true} if this network does not broadcast its SSID, so an
1472      * SSID-specific probe request must be used for scans.
1473      */
getHiddenSSID()1474     public boolean getHiddenSSID() {
1475         return mIsHiddenSsid;
1476     }
1477 
1478     /**
1479      * Sets whether or not this network is using a hidden SSID. This value should be set from the
1480      * corresponding {@link WifiConfiguration} of the network.
1481      * @hide
1482      */
setHiddenSSID(boolean isHiddenSsid)1483     public void setHiddenSSID(boolean isHiddenSsid) {
1484         mIsHiddenSsid = isHiddenSsid;
1485     }
1486 
1487     /**
1488      * Map a supplicant state into a fine-grained network connectivity state.
1489      * @param suppState the supplicant state
1490      * @return the corresponding {@link DetailedState}
1491      */
getDetailedStateOf(SupplicantState suppState)1492     public static DetailedState getDetailedStateOf(SupplicantState suppState) {
1493         return stateMap.get(suppState);
1494     }
1495 
1496     /**
1497      * Set the <code>SupplicantState</code> from the string name
1498      * of the state.
1499      * @param stateName the name of the state, as a <code>String</code> returned
1500      * in an event sent by {@code wpa_supplicant}.
1501      */
1502     @UnsupportedAppUsage
setSupplicantState(String stateName)1503     void setSupplicantState(String stateName) {
1504         mSupplicantState = valueOf(stateName);
1505     }
1506 
valueOf(String stateName)1507     static SupplicantState valueOf(String stateName) {
1508         if ("4WAY_HANDSHAKE".equalsIgnoreCase(stateName))
1509             return SupplicantState.FOUR_WAY_HANDSHAKE;
1510         else {
1511             try {
1512                 return SupplicantState.valueOf(stateName.toUpperCase(Locale.ROOT));
1513             } catch (IllegalArgumentException e) {
1514                 return SupplicantState.INVALID;
1515             }
1516         }
1517     }
1518 
1519     /**
1520      * Remove double quotes (") surrounding a SSID string, if present. Otherwise, return the
1521      * string unmodified. Return null if the input string was null.
1522      * @hide
1523      */
1524     @Nullable
1525     @SystemApi
sanitizeSsid(@ullable String string)1526     public static String sanitizeSsid(@Nullable String string) {
1527         return removeDoubleQuotes(string);
1528     }
1529 
1530     /** @hide */
1531     @UnsupportedAppUsage
1532     @Nullable
removeDoubleQuotes(@ullable String string)1533     public static String removeDoubleQuotes(@Nullable String string) {
1534         if (string == null) return null;
1535         final int length = string.length();
1536         if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
1537             return string.substring(1, length - 1);
1538         }
1539         return string;
1540     }
1541 
1542     @Override
toString()1543     public String toString() {
1544         StringBuffer sb = new StringBuffer();
1545         String none = "<none>";
1546 
1547         sb.append("SSID: ").append(getSSID())
1548                 .append(", BSSID: ").append(mBSSID == null ? none : mBSSID)
1549                 .append(", MAC: ").append(mMacAddress == null ? none : mMacAddress)
1550                 .append(", IP: ").append(mIpAddress)
1551                 .append(", Security type: ").append(mSecurityType)
1552                 .append(", Supplicant state: ")
1553                 .append(mSupplicantState == null ? none : mSupplicantState)
1554                 .append(", Wi-Fi standard: ").append(ScanResult.wifiStandardToString(mWifiStandard))
1555                 .append(", RSSI: ").append(mRssi)
1556                 .append(", Link speed: ").append(mLinkSpeed).append(LINK_SPEED_UNITS)
1557                 .append(", Tx Link speed: ").append(mTxLinkSpeed).append(LINK_SPEED_UNITS)
1558                 .append(", Max Supported Tx Link speed: ")
1559                 .append(mMaxSupportedTxLinkSpeed).append(LINK_SPEED_UNITS)
1560                 .append(", Rx Link speed: ").append(mRxLinkSpeed).append(LINK_SPEED_UNITS)
1561                 .append(", Max Supported Rx Link speed: ")
1562                 .append(mMaxSupportedRxLinkSpeed).append(LINK_SPEED_UNITS)
1563                 .append(", Frequency: ").append(mFrequency).append(FREQUENCY_UNITS)
1564                 .append(", Net ID: ").append(mNetworkId)
1565                 .append(", Metered hint: ").append(mMeteredHint)
1566                 .append(", score: ").append(Integer.toString(score))
1567                 .append(", isUsable: ").append(mIsUsable)
1568                 .append(", CarrierMerged: ").append(mCarrierMerged)
1569                 .append(", SubscriptionId: ").append(mSubscriptionId)
1570                 .append(", IsPrimary: ").append(mIsPrimary)
1571                 .append(", Trusted: ").append(mTrusted)
1572                 .append(", Restricted: ").append(mRestricted)
1573                 .append(", Ephemeral: ").append(mEphemeral)
1574                 .append(", OEM paid: ").append(mOemPaid)
1575                 .append(", OEM private: ").append(mOemPrivate)
1576                 .append(", OSU AP: ").append(mOsuAp)
1577                 .append(", FQDN: ").append(mFqdn == null ? none : mFqdn)
1578                 .append(", Provider friendly name: ")
1579                 .append(mProviderFriendlyName == null ? none : mProviderFriendlyName)
1580                 .append(", Requesting package name: ")
1581                 .append(mRequestingPackageName == null ? none : mRequestingPackageName)
1582                 .append(mNetworkKey == null ? none : mNetworkKey)
1583                 .append("MLO Information: ")
1584                 .append(", Is TID-To-Link negotiation supported by the AP: ")
1585                 .append(mApTidToLinkMappingNegotiationSupported)
1586                 .append(", AP MLD Address: ").append(
1587                         mApMldMacAddress == null ? none : mApMldMacAddress.toString())
1588                 .append(", AP MLO Link Id: ").append(
1589                         mApMldMacAddress == null ? none : mApMloLinkId)
1590                 .append(", AP MLO Affiliated links: ").append(
1591                         mApMldMacAddress == null ? none : mAffiliatedMloLinks)
1592                 .append(", Vendor Data: ").append(
1593                         mVendorData == null || mVendorData.isEmpty() ? none : mVendorData);
1594 
1595         return sb.toString();
1596     }
1597 
1598     /** Implement the Parcelable interface {@hide} */
describeContents()1599     public int describeContents() {
1600         return 0;
1601     }
1602 
shouldRedactLocationSensitiveFields(long redactions)1603     private boolean shouldRedactLocationSensitiveFields(long redactions) {
1604         return (redactions & NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION) != 0;
1605     }
1606 
shouldRedactLocalMacAddressFields(long redactions)1607     private boolean shouldRedactLocalMacAddressFields(long redactions) {
1608         return (redactions & NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS) != 0;
1609     }
1610 
shouldRedactNetworkSettingsFields(long redactions)1611     private boolean shouldRedactNetworkSettingsFields(long redactions) {
1612         return (redactions & NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS) != 0;
1613     }
1614 
1615     /** Implement the Parcelable interface {@hide} */
writeToParcel(Parcel dest, int flags)1616     public void writeToParcel(Parcel dest, int flags) {
1617         dest.writeInt(mNetworkId);
1618         dest.writeInt(mRssi);
1619         dest.writeInt(mLinkSpeed);
1620         dest.writeInt(mTxLinkSpeed);
1621         dest.writeInt(mRxLinkSpeed);
1622         dest.writeInt(mFrequency);
1623         if (mIpAddress != null) {
1624             dest.writeByte((byte)1);
1625             dest.writeByteArray(mIpAddress.getAddress());
1626         } else {
1627             dest.writeByte((byte)0);
1628         }
1629         if (mWifiSsid != null) {
1630             dest.writeInt(1);
1631             mWifiSsid.writeToParcel(dest, flags);
1632         } else {
1633             dest.writeInt(0);
1634         }
1635         dest.writeString(mBSSID);
1636         dest.writeString(mMacAddress);
1637         dest.writeInt(mMeteredHint ? 1 : 0);
1638         dest.writeInt(mEphemeral ? 1 : 0);
1639         dest.writeInt(mTrusted ? 1 : 0);
1640         dest.writeInt(mOemPaid ? 1 : 0);
1641         dest.writeInt(mOemPrivate ? 1 : 0);
1642         dest.writeInt(mCarrierMerged ? 1 : 0);
1643         dest.writeInt(score);
1644         dest.writeBoolean(mIsUsable);
1645         dest.writeLong(txSuccess);
1646         dest.writeDouble(mSuccessfulTxPacketsPerSecond);
1647         dest.writeLong(txRetries);
1648         dest.writeDouble(mTxRetriedTxPacketsPerSecond);
1649         dest.writeLong(txBad);
1650         dest.writeDouble(mLostTxPacketsPerSecond);
1651         dest.writeLong(rxSuccess);
1652         dest.writeDouble(mSuccessfulRxPacketsPerSecond);
1653         mSupplicantState.writeToParcel(dest, flags);
1654         dest.writeInt(mOsuAp ? 1 : 0);
1655         dest.writeString(mRequestingPackageName);
1656         dest.writeString(mFqdn);
1657         dest.writeString(mProviderFriendlyName);
1658         dest.writeInt(mWifiStandard);
1659         dest.writeInt(mMaxSupportedTxLinkSpeed);
1660         dest.writeInt(mMaxSupportedRxLinkSpeed);
1661         dest.writeString(mPasspointUniqueId);
1662         dest.writeInt(mSubscriptionId);
1663         dest.writeTypedList(mInformationElements);
1664         if (SdkLevel.isAtLeastS()) {
1665             dest.writeInt(mIsPrimary);
1666         }
1667         dest.writeInt(mSecurityType);
1668         dest.writeInt(mRestricted ? 1 : 0);
1669         dest.writeString(mNetworkKey);
1670         dest.writeParcelable(mApMldMacAddress, flags);
1671         dest.writeInt(mApMloLinkId);
1672         dest.writeTypedList(mAffiliatedMloLinks);
1673         dest.writeBoolean(mApTidToLinkMappingNegotiationSupported);
1674         dest.writeList(mVendorData);
1675     }
1676 
1677     /** Implement the Parcelable interface {@hide} */
1678     @UnsupportedAppUsage
1679     public static final @android.annotation.NonNull Creator<WifiInfo> CREATOR =
1680         new Creator<WifiInfo>() {
1681             public WifiInfo createFromParcel(Parcel in) {
1682                 WifiInfo info = new WifiInfo();
1683                 info.setNetworkId(in.readInt());
1684                 info.setRssi(in.readInt());
1685                 info.setLinkSpeed(in.readInt());
1686                 info.setTxLinkSpeedMbps(in.readInt());
1687                 info.setRxLinkSpeedMbps(in.readInt());
1688                 info.setFrequency(in.readInt());
1689                 if (in.readByte() == 1) {
1690                     try {
1691                         info.setInetAddress(InetAddress.getByAddress(in.createByteArray()));
1692                     } catch (UnknownHostException e) {}
1693                 }
1694                 if (in.readInt() == 1) {
1695                     info.mWifiSsid = WifiSsid.CREATOR.createFromParcel(in);
1696                 }
1697                 info.mBSSID = in.readString();
1698                 info.mMacAddress = in.readString();
1699                 info.mMeteredHint = in.readInt() != 0;
1700                 info.mEphemeral = in.readInt() != 0;
1701                 info.mTrusted = in.readInt() != 0;
1702                 info.mOemPaid = in.readInt() != 0;
1703                 info.mOemPrivate = in.readInt() != 0;
1704                 info.mCarrierMerged = in.readInt() != 0;
1705                 info.score = in.readInt();
1706                 info.mIsUsable = in.readBoolean();
1707                 info.txSuccess = in.readLong();
1708                 info.mSuccessfulTxPacketsPerSecond = in.readDouble();
1709                 info.txRetries = in.readLong();
1710                 info.mTxRetriedTxPacketsPerSecond = in.readDouble();
1711                 info.txBad = in.readLong();
1712                 info.mLostTxPacketsPerSecond = in.readDouble();
1713                 info.rxSuccess = in.readLong();
1714                 info.mSuccessfulRxPacketsPerSecond = in.readDouble();
1715                 info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
1716                 info.mOsuAp = in.readInt() != 0;
1717                 info.mRequestingPackageName = in.readString();
1718                 info.mFqdn = in.readString();
1719                 info.mProviderFriendlyName = in.readString();
1720                 info.mWifiStandard = in.readInt();
1721                 info.mMaxSupportedTxLinkSpeed = in.readInt();
1722                 info.mMaxSupportedRxLinkSpeed = in.readInt();
1723                 info.mPasspointUniqueId = in.readString();
1724                 info.mSubscriptionId = in.readInt();
1725                 info.mInformationElements = in.createTypedArrayList(
1726                         ScanResult.InformationElement.CREATOR);
1727                 if (SdkLevel.isAtLeastS()) {
1728                     info.mIsPrimary = in.readInt();
1729                 }
1730                 info.mSecurityType = in.readInt();
1731                 info.mRestricted = in.readInt() != 0;
1732                 info.mNetworkKey = in.readString();
1733 
1734                 info.mApMldMacAddress = in.readParcelable(MacAddress.class.getClassLoader());
1735                 info.mApMloLinkId = in.readInt();
1736                 info.mAffiliatedMloLinks = in.createTypedArrayList(MloLink.CREATOR);
1737                 info.mApTidToLinkMappingNegotiationSupported = in.readBoolean();
1738                 info.mVendorData = ParcelUtil.readOuiKeyedDataList(in);
1739                 return info;
1740             }
1741 
1742             public WifiInfo[] newArray(int size) {
1743                 return new WifiInfo[size];
1744             }
1745         };
1746 
1747     /**
1748      * Set the Passpoint unique identifier for the current connection
1749      *
1750      * @param passpointUniqueId Unique identifier
1751      * @hide
1752      */
setPasspointUniqueId(@ullable String passpointUniqueId)1753     public void setPasspointUniqueId(@Nullable String passpointUniqueId) {
1754         mPasspointUniqueId = passpointUniqueId;
1755     }
1756 
1757     /**
1758      * Get the Passpoint unique identifier for the current connection
1759      *
1760      * @return Passpoint unique identifier, or null if this connection is not Passpoint.
1761      */
1762     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
getPasspointUniqueId()1763     public @Nullable String getPasspointUniqueId() {
1764         return mPasspointUniqueId;
1765     }
1766 
1767     /**
1768      * Set the information elements found in the becaon of the connected bssid.
1769      * @hide
1770      */
setInformationElements(@ullable List<ScanResult.InformationElement> infoElements)1771     public void setInformationElements(@Nullable List<ScanResult.InformationElement> infoElements) {
1772         if (infoElements == null) {
1773             mInformationElements = null;
1774             return;
1775         }
1776         mInformationElements = new ArrayList<>(infoElements);
1777     }
1778 
1779     /**
1780      * Get all information elements found in the beacon of the connected bssid.
1781      * <p>
1782      * The information elements will be {@code null} if there is no network currently connected or
1783      * if the caller has insufficient permissions to access the info elements.
1784      * </p>
1785      *
1786      * @return List of information elements {@link ScanResult.InformationElement} or null.
1787      */
1788     @Nullable
1789     @SuppressWarnings("NullableCollection")
getInformationElements()1790     public List<ScanResult.InformationElement> getInformationElements() {
1791         if (mInformationElements == null) return null;
1792         return new ArrayList<>(mInformationElements);
1793     }
1794 
1795     /**
1796      * @see #isPrimary()
1797      * @hide
1798      */
setIsPrimary(boolean isPrimary)1799     public void setIsPrimary(boolean isPrimary) {
1800         mIsPrimary = isPrimary ? IS_PRIMARY_TRUE : IS_PRIMARY_FALSE;
1801     }
1802 
1803     /**
1804      * Returns whether this is the primary wifi connection or not.
1805      *
1806      * Wifi service considers this connection to be the best among all Wifi connections, and this
1807      * connection should be the one surfaced to the user if only one can be displayed.
1808      *
1809      * Note that the default route (chosen by Connectivity Service) may not correspond to the
1810      * primary Wifi connection e.g. when there exists a better cellular network, or if the
1811      * primary Wifi connection doesn't have internet access.
1812      *
1813      * @return whether this is the primary connection or not.
1814      *
1815      * @hide
1816      */
1817     @RequiresApi(Build.VERSION_CODES.S)
1818     @RequiresPermission(Manifest.permission.NETWORK_SETTINGS)
1819     @SystemApi
isPrimary()1820     public boolean isPrimary() {
1821         if (!SdkLevel.isAtLeastS()) {
1822             // Intentional - since we don't support STA + STA on older devices, this field
1823             // is redundant. Don't allow anyone to use this.
1824             throw new UnsupportedOperationException();
1825         }
1826         if (mIsPrimary == IS_PRIMARY_NO_PERMISSION) {
1827             throw new SecurityException("Not allowed to access this field");
1828         }
1829         return mIsPrimary == IS_PRIMARY_TRUE;
1830     }
1831 
getSortedMloLinkList(List<MloLink> list)1832     private List<MloLink> getSortedMloLinkList(List<MloLink> list) {
1833         List<MloLink> newList = new ArrayList<MloLink>(list);
1834         Collections.sort(newList, new Comparator<MloLink>() {
1835             @Override
1836             public int compare(MloLink lhs, MloLink rhs) {
1837                 return lhs.getLinkId() -  rhs.getLinkId();
1838             }
1839         });
1840 
1841         return newList;
1842     }
1843 
1844     @Override
equals(Object that)1845     public boolean equals(Object that) {
1846         if (this == that) return true;
1847 
1848         // Potential API behavior change, so don't change behavior on older devices.
1849         if (!SdkLevel.isAtLeastS()) return false;
1850 
1851         if (!(that instanceof WifiInfo)) return false;
1852 
1853         WifiInfo thatWifiInfo = (WifiInfo) that;
1854 
1855         // compare the MLO affiliated links irrespective of the order
1856         if (!Objects.equals(getSortedMloLinkList(mAffiliatedMloLinks),
1857                   getSortedMloLinkList(thatWifiInfo.mAffiliatedMloLinks))) {
1858             return false;
1859         }
1860 
1861         return Objects.equals(mWifiSsid, thatWifiInfo.mWifiSsid)
1862                 && Objects.equals(mBSSID, thatWifiInfo.mBSSID)
1863                 && Objects.equals(mApMldMacAddress, thatWifiInfo.mApMldMacAddress)
1864                 && mApMloLinkId == thatWifiInfo.mApMloLinkId
1865                 && Objects.equals(mNetworkId, thatWifiInfo.mNetworkId)
1866                 && Objects.equals(mRssi, thatWifiInfo.mRssi)
1867                 && Objects.equals(mSupplicantState, thatWifiInfo.mSupplicantState)
1868                 && Objects.equals(mLinkSpeed, thatWifiInfo.mLinkSpeed)
1869                 && Objects.equals(mTxLinkSpeed, thatWifiInfo.mTxLinkSpeed)
1870                 && Objects.equals(mRxLinkSpeed, thatWifiInfo.mRxLinkSpeed)
1871                 && Objects.equals(mFrequency, thatWifiInfo.mFrequency)
1872                 && Objects.equals(mIpAddress, thatWifiInfo.mIpAddress)
1873                 && Objects.equals(mMacAddress, thatWifiInfo.mMacAddress)
1874                 && Objects.equals(mMeteredHint, thatWifiInfo.mMeteredHint)
1875                 && Objects.equals(mEphemeral, thatWifiInfo.mEphemeral)
1876                 && Objects.equals(mTrusted, thatWifiInfo.mTrusted)
1877                 && Objects.equals(mOemPaid, thatWifiInfo.mOemPaid)
1878                 && Objects.equals(mOemPrivate, thatWifiInfo.mOemPrivate)
1879                 && Objects.equals(mCarrierMerged, thatWifiInfo.mCarrierMerged)
1880                 && Objects.equals(mRequestingPackageName, thatWifiInfo.mRequestingPackageName)
1881                 && Objects.equals(mOsuAp, thatWifiInfo.mOsuAp)
1882                 && Objects.equals(mFqdn, thatWifiInfo.mFqdn)
1883                 && Objects.equals(mProviderFriendlyName, thatWifiInfo.mProviderFriendlyName)
1884                 && Objects.equals(mSubscriptionId, thatWifiInfo.mSubscriptionId)
1885                 && Objects.equals(txBad, thatWifiInfo.txBad)
1886                 && Objects.equals(txRetries, thatWifiInfo.txRetries)
1887                 && Objects.equals(txSuccess, thatWifiInfo.txSuccess)
1888                 && Objects.equals(rxSuccess, thatWifiInfo.rxSuccess)
1889                 && Objects.equals(mLostTxPacketsPerSecond, thatWifiInfo.mLostTxPacketsPerSecond)
1890                 && Objects.equals(mTxRetriedTxPacketsPerSecond,
1891                 thatWifiInfo.mTxRetriedTxPacketsPerSecond)
1892                 && Objects.equals(mSuccessfulTxPacketsPerSecond,
1893                 thatWifiInfo.mSuccessfulTxPacketsPerSecond)
1894                 && Objects.equals(mSuccessfulRxPacketsPerSecond,
1895                 thatWifiInfo.mSuccessfulRxPacketsPerSecond)
1896                 && Objects.equals(score, thatWifiInfo.score)
1897                 && Objects.equals(mIsUsable, thatWifiInfo.mIsUsable)
1898                 && Objects.equals(mWifiStandard, thatWifiInfo.mWifiStandard)
1899                 && Objects.equals(mMaxSupportedTxLinkSpeed, thatWifiInfo.mMaxSupportedTxLinkSpeed)
1900                 && Objects.equals(mMaxSupportedRxLinkSpeed, thatWifiInfo.mMaxSupportedRxLinkSpeed)
1901                 && Objects.equals(mPasspointUniqueId, thatWifiInfo.mPasspointUniqueId)
1902                 && Objects.equals(mInformationElements, thatWifiInfo.mInformationElements)
1903                 && mIsPrimary == thatWifiInfo.mIsPrimary
1904                 && mSecurityType == thatWifiInfo.mSecurityType
1905                 && mRestricted == thatWifiInfo.mRestricted
1906                 && Objects.equals(mNetworkKey, thatWifiInfo.mNetworkKey)
1907                 && mApTidToLinkMappingNegotiationSupported
1908                 == thatWifiInfo.mApTidToLinkMappingNegotiationSupported
1909                 && Objects.equals(mVendorData, thatWifiInfo.mVendorData);
1910     }
1911 
1912     @Override
hashCode()1913     public int hashCode() {
1914         // Potential API behavior change, so don't change behavior on older devices.
1915         if (!SdkLevel.isAtLeastS()) return System.identityHashCode(this);
1916 
1917         return Objects.hash(mWifiSsid,
1918                 mBSSID,
1919                 mApMldMacAddress,
1920                 mApMloLinkId,
1921                 mAffiliatedMloLinks,
1922                 mNetworkId,
1923                 mRssi,
1924                 mSupplicantState,
1925                 mLinkSpeed,
1926                 mTxLinkSpeed,
1927                 mRxLinkSpeed,
1928                 mFrequency,
1929                 mIpAddress,
1930                 mMacAddress,
1931                 mMeteredHint,
1932                 mEphemeral,
1933                 mTrusted,
1934                 mOemPaid,
1935                 mOemPrivate,
1936                 mCarrierMerged,
1937                 mRequestingPackageName,
1938                 mOsuAp,
1939                 mFqdn,
1940                 mProviderFriendlyName,
1941                 mSubscriptionId,
1942                 txBad,
1943                 txRetries,
1944                 txSuccess,
1945                 rxSuccess,
1946                 mLostTxPacketsPerSecond,
1947                 mTxRetriedTxPacketsPerSecond,
1948                 mSuccessfulTxPacketsPerSecond,
1949                 mSuccessfulRxPacketsPerSecond,
1950                 score,
1951                 mIsUsable,
1952                 mWifiStandard,
1953                 mMaxSupportedTxLinkSpeed,
1954                 mMaxSupportedRxLinkSpeed,
1955                 mPasspointUniqueId,
1956                 mInformationElements,
1957                 mIsPrimary,
1958                 mSecurityType,
1959                 mRestricted,
1960                 mNetworkKey,
1961                 mApTidToLinkMappingNegotiationSupported,
1962                 mVendorData);
1963     }
1964 
1965     /**
1966      * Create a copy of a {@link WifiInfo} with some fields redacted based on the permissions
1967      * held by the receiving app.
1968      *
1969      * @param redactions bitmask of redactions that needs to be performed on this instance.
1970      * @return Copy of this instance with the necessary redactions.
1971      */
1972     @Override
1973     @NonNull
makeCopy(long redactions)1974     public WifiInfo makeCopy(long redactions) {
1975         return new WifiInfo(this, redactions);
1976     }
1977 
1978     /**
1979      * Returns a bitmask of all the applicable redactions (based on the permissions held by the
1980      * receiving app) to be performed on this TransportInfo.
1981      *
1982      * @return bitmask of redactions applicable on this instance.
1983      */
1984     @Override
getApplicableRedactions()1985     public long getApplicableRedactions() {
1986         return NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION
1987                 | NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS
1988                 | NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
1989     }
1990 
1991     /**
1992      * Set the security type of the current connection
1993      * @hide
1994      */
setCurrentSecurityType(@ifiConfiguration.SecurityType int securityType)1995     public void setCurrentSecurityType(@WifiConfiguration.SecurityType int securityType) {
1996         mSecurityType = convertWifiConfigurationSecurityType(securityType);
1997     }
1998 
1999     /**
2000      * Clear the last set security type
2001      * @hide
2002      */
clearCurrentSecurityType()2003     public void clearCurrentSecurityType() {
2004         mSecurityType = SECURITY_TYPE_UNKNOWN;
2005     }
2006 
2007     /**
2008      * Returns the security type of the current 802.11 network connection.
2009      *
2010      * @return the security type, or {@link #SECURITY_TYPE_UNKNOWN} if not currently connected.
2011      */
getCurrentSecurityType()2012     public @WifiAnnotations.SecurityType int getCurrentSecurityType() {
2013         return mSecurityType;
2014     }
2015 
2016     /**
2017      * Converts the WifiConfiguration.SecurityType to a WifiInfo.SecurityType
2018      * @param wifiConfigSecurity WifiConfiguration.SecurityType to convert
2019      * @return security type as a WifiInfo.SecurityType
2020      * @hide
2021      */
convertWifiConfigurationSecurityType( @ifiConfiguration.SecurityType int wifiConfigSecurity)2022     public static @WifiAnnotations.SecurityType int convertWifiConfigurationSecurityType(
2023             @WifiConfiguration.SecurityType int wifiConfigSecurity) {
2024         switch (wifiConfigSecurity) {
2025             case WifiConfiguration.SECURITY_TYPE_OPEN:
2026                 return SECURITY_TYPE_OPEN;
2027             case WifiConfiguration.SECURITY_TYPE_WEP:
2028                 return SECURITY_TYPE_WEP;
2029             case WifiConfiguration.SECURITY_TYPE_PSK:
2030                 return SECURITY_TYPE_PSK;
2031             case WifiConfiguration.SECURITY_TYPE_EAP:
2032                 return SECURITY_TYPE_EAP;
2033             case WifiConfiguration.SECURITY_TYPE_SAE:
2034                 return SECURITY_TYPE_SAE;
2035             case WifiConfiguration.SECURITY_TYPE_OWE:
2036                 return SECURITY_TYPE_OWE;
2037             case WifiConfiguration.SECURITY_TYPE_WAPI_PSK:
2038                 return SECURITY_TYPE_WAPI_PSK;
2039             case WifiConfiguration.SECURITY_TYPE_WAPI_CERT:
2040                 return SECURITY_TYPE_WAPI_CERT;
2041             case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE:
2042                 return SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
2043             case WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT:
2044                 return SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
2045             case WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2:
2046                 return SECURITY_TYPE_PASSPOINT_R1_R2;
2047             case WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3:
2048                 return SECURITY_TYPE_PASSPOINT_R3;
2049             case WifiConfiguration.SECURITY_TYPE_DPP:
2050                 return SECURITY_TYPE_DPP;
2051             default:
2052                 return SECURITY_TYPE_UNKNOWN;
2053         }
2054     }
2055 
2056     /**
2057      * Utility method to convert WifiInfo.SecurityType to DevicePolicyManager.WifiSecurity
2058      * @param securityType WifiInfo.SecurityType to convert
2059      * @return DevicePolicyManager.WifiSecurity security level, or
2060      * {@link #DPM_SECURITY_TYPE_UNKNOWN} for unknown security types
2061      * @hide
2062      */
convertSecurityTypeToDpmWifiSecurity( @ifiAnnotations.SecurityType int securityType)2063     public static int convertSecurityTypeToDpmWifiSecurity(
2064             @WifiAnnotations.SecurityType int securityType) {
2065         switch (securityType) {
2066             case SECURITY_TYPE_OPEN:
2067             case SECURITY_TYPE_OWE:
2068                 return DevicePolicyManager.WIFI_SECURITY_OPEN;
2069             case SECURITY_TYPE_WEP:
2070             case SECURITY_TYPE_PSK:
2071             case SECURITY_TYPE_SAE:
2072             case SECURITY_TYPE_WAPI_PSK:
2073                 return DevicePolicyManager.WIFI_SECURITY_PERSONAL;
2074             case SECURITY_TYPE_EAP:
2075             case SECURITY_TYPE_EAP_WPA3_ENTERPRISE:
2076             case SECURITY_TYPE_PASSPOINT_R1_R2:
2077             case SECURITY_TYPE_PASSPOINT_R3:
2078             case SECURITY_TYPE_WAPI_CERT:
2079                 return DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_EAP;
2080             case SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT:
2081                 return DevicePolicyManager.WIFI_SECURITY_ENTERPRISE_192;
2082             default:
2083                 return DPM_SECURITY_TYPE_UNKNOWN;
2084         }
2085     }
2086 
2087     /**
2088      * Set the network key for the current Wi-Fi network.
2089      *
2090      * Now we are using this identity to be a key when storing Wi-Fi data usage data.
2091      * See: {@link WifiConfiguration#getNetworkKeyFromSecurityType(int)}.
2092      *
2093      * @param currentNetworkKey the network key of the current Wi-Fi network.
2094      * @hide
2095      */
setNetworkKey(@onNull String currentNetworkKey)2096     public void setNetworkKey(@NonNull String currentNetworkKey) {
2097         mNetworkKey = currentNetworkKey;
2098     }
2099 
2100     /**
2101      * Returns the network key of the current Wi-Fi network.
2102      *
2103      * The network key may be {@code null}, if there is no network currently connected
2104      * or if the caller has insufficient permissions to access the network key.
2105      *
2106      * @hide
2107      */
2108     @SystemApi
2109     @Nullable
getNetworkKey()2110     public String getNetworkKey() {
2111         return mNetworkKey;
2112     }
2113 
2114     /**
2115      * TID-to-Link mapping negotiation is an optional feature. This API returns whether the feature
2116      * is supported by the AP.
2117      *
2118      * @return Return true if TID-to-Link mapping negotiation is supported by the AP, otherwise
2119      * false.
2120      *
2121      * @hide
2122      */
2123     @SystemApi
isApTidToLinkMappingNegotiationSupported()2124     public boolean isApTidToLinkMappingNegotiationSupported() {
2125         return mApTidToLinkMappingNegotiationSupported;
2126     }
2127 
2128     /** @hide */
enableApTidToLinkMappingNegotiationSupport(boolean enable)2129     public void enableApTidToLinkMappingNegotiationSupport(boolean enable) {
2130         mApTidToLinkMappingNegotiationSupported = enable;
2131     }
2132 
2133     /**
2134      * Return the vendor-provided configuration data, if it exists. See also {@link
2135      * #setVendorData(List)}
2136      *
2137      * @return Vendor configuration data, or empty list if it does not exist.
2138      * @hide
2139      */
2140     @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
2141     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
2142     @NonNull
2143     @SystemApi
getVendorData()2144     public List<OuiKeyedData> getVendorData() {
2145         if (!SdkLevel.isAtLeastV()) {
2146             throw new UnsupportedOperationException();
2147         }
2148         return mVendorData;
2149     }
2150 
2151     /**
2152      * Set additional vendor-provided configuration data.
2153      *
2154      * @param vendorData List of {@link OuiKeyedData} containing the vendor-provided
2155      *     configuration data. Note that multiple elements with the same OUI are allowed.
2156      * @hide
2157      */
2158     @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
2159     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
2160     @SystemApi
setVendorData(@onNull List<OuiKeyedData> vendorData)2161     public void setVendorData(@NonNull List<OuiKeyedData> vendorData) {
2162         if (!SdkLevel.isAtLeastV()) {
2163             throw new UnsupportedOperationException();
2164         }
2165         if (vendorData == null) {
2166             throw new IllegalArgumentException("setVendorData received a null value");
2167         }
2168         mVendorData = new ArrayList<>(vendorData);
2169     }
2170 }
2171