1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.wifi;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SuppressLint;
25 import android.annotation.SystemApi;
26 import android.compat.annotation.UnsupportedAppUsage;
27 import android.content.pm.PackageManager;
28 import android.net.IpConfiguration;
29 import android.net.IpConfiguration.ProxySettings;
30 import android.net.MacAddress;
31 import android.net.NetworkSpecifier;
32 import android.net.ProxyInfo;
33 import android.net.StaticIpConfiguration;
34 import android.net.Uri;
35 import android.os.Build;
36 import android.os.Parcel;
37 import android.os.ParcelUuid;
38 import android.os.Parcelable;
39 import android.os.SystemClock;
40 import android.os.UserHandle;
41 import android.telephony.SubscriptionInfo;
42 import android.telephony.SubscriptionManager;
43 import android.telephony.TelephonyManager;
44 import android.text.TextUtils;
45 import android.util.Log;
46 import android.util.SparseArray;
47 
48 import androidx.annotation.RequiresApi;
49 
50 import com.android.internal.annotations.VisibleForTesting;
51 import com.android.modules.utils.build.SdkLevel;
52 import com.android.net.module.util.MacAddressUtils;
53 import com.android.wifi.flags.Flags;
54 
55 import java.lang.annotation.Retention;
56 import java.lang.annotation.RetentionPolicy;
57 import java.time.Instant;
58 import java.time.LocalDateTime;
59 import java.time.ZoneId;
60 import java.util.ArrayList;
61 import java.util.Arrays;
62 import java.util.BitSet;
63 import java.util.Calendar;
64 import java.util.Collections;
65 import java.util.HashMap;
66 import java.util.HashSet;
67 import java.util.List;
68 import java.util.Objects;
69 import java.util.Set;
70 
71 /**
72  * A class representing a configured Wi-Fi network, including the
73  * security configuration.
74  *
75  * @deprecated Use {@link WifiNetworkSpecifier.Builder} to create {@link NetworkSpecifier} and
76  * {@link WifiNetworkSuggestion.Builder} to create {@link WifiNetworkSuggestion}. This class can
77  * still be used with privileged APIs such as
78  * {@link WifiManager#addNetwork(WifiConfiguration)}.
79  */
80 @Deprecated
81 public class WifiConfiguration implements Parcelable {
82     private static final String TAG = "WifiConfiguration";
83     /**
84      * Current Version of the Backup Serializer.
85     */
86     private static final int BACKUP_VERSION = 3;
87     /** {@hide} */
88     public static final String ssidVarName = "ssid";
89     /** {@hide} */
90     public static final String bssidVarName = "bssid";
91     /** {@hide} */
92     public static final String pskVarName = "psk";
93     /** {@hide} */
94     @Deprecated @UnsupportedAppUsage
95     public static final String[] wepKeyVarNames = {"wep_key0", "wep_key1", "wep_key2", "wep_key3"};
96     /** {@hide} */
97     @Deprecated
98     public static final String wepTxKeyIdxVarName = "wep_tx_keyidx";
99     /** {@hide} */
100     public static final String priorityVarName = "priority";
101     /** {@hide} */
102     public static final String hiddenSSIDVarName = "scan_ssid";
103     /** {@hide} */
104     public static final String pmfVarName = "ieee80211w";
105     /** {@hide} */
106     public static final String updateIdentiferVarName = "update_identifier";
107     /**
108      * The network ID for an invalid network.
109      *
110      * @hide
111      */
112     @SystemApi
113     public static final int INVALID_NETWORK_ID = -1;
114     /** {@hide} */
115     public static final int LOCAL_ONLY_NETWORK_ID = -2;
116 
117     /** {@hide} */
118     private String mPasspointManagementObjectTree;
119     /** {@hide} */
120     private static final int MAXIMUM_RANDOM_MAC_GENERATION_RETRY = 3;
121 
122     /**
123      * Recognized key management schemes.
124      */
125     public static class KeyMgmt {
KeyMgmt()126         private KeyMgmt() { }
127 
128         /** @hide */
129         @Retention(RetentionPolicy.SOURCE)
130         @IntDef(value = {
131                 NONE,
132                 WPA_PSK,
133                 WPA_EAP,
134                 IEEE8021X,
135                 WPA2_PSK,
136                 OSEN,
137                 FT_PSK,
138                 FT_EAP,
139                 SAE,
140                 OWE,
141                 SUITE_B_192,
142                 WPA_PSK_SHA256,
143                 WPA_EAP_SHA256,
144                 WAPI_PSK,
145                 WAPI_CERT,
146                 FILS_SHA256,
147                 FILS_SHA384,
148                 DPP})
149         public @interface KeyMgmtScheme {}
150 
151         /** WPA is not used; plaintext or static WEP could be used. */
152         public static final int NONE = 0;
153         /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */
154         public static final int WPA_PSK = 1;
155         /** WPA using EAP authentication. Generally used with an external authentication server. */
156         public static final int WPA_EAP = 2;
157         /**
158          * IEEE 802.1X using EAP authentication and (optionally) dynamically
159          * generated WEP keys.
160          */
161         public static final int IEEE8021X = 3;
162 
163         /**
164          * WPA2 pre-shared key for use with soft access point
165          * (requires {@code preSharedKey} to be specified).
166          */
167         public static final int WPA2_PSK = 4;
168         /**
169          * Hotspot 2.0 r2 OSEN:
170          */
171         public static final int OSEN = 5;
172 
173         /**
174          * IEEE 802.11r Fast BSS Transition with PSK authentication.
175          */
176         public static final int FT_PSK = 6;
177 
178         /**
179          * IEEE 802.11r Fast BSS Transition with EAP authentication.
180          */
181         public static final int FT_EAP = 7;
182 
183         /**
184          * Simultaneous Authentication of Equals
185          */
186         public static final int SAE = 8;
187 
188         /**
189          * Opportunististic Wireless Encryption
190          */
191         public static final int OWE = 9;
192 
193         /**
194          * SUITE_B_192 192 bit level
195          */
196         public static final int SUITE_B_192 = 10;
197 
198         /**
199          * WPA pre-shared key with stronger SHA256-based algorithms.
200          */
201         public static final int WPA_PSK_SHA256 = 11;
202 
203         /**
204          * WPA using EAP authentication with stronger SHA256-based algorithms.
205          */
206         public static final int WPA_EAP_SHA256 = 12;
207 
208         /**
209          * WAPI pre-shared key (requires {@code preSharedKey} to be specified).
210          */
211         public static final int WAPI_PSK = 13;
212 
213         /**
214          * WAPI certificate to be specified.
215          */
216         public static final int WAPI_CERT = 14;
217 
218         /**
219         * IEEE 802.11ai FILS SK with SHA256
220         */
221         public static final int FILS_SHA256 = 15;
222         /**
223          * IEEE 802.11ai FILS SK with SHA384:
224          */
225         public static final int FILS_SHA384 = 16;
226 
227         /**
228          * Easy Connect - AKA Device Provisioning Protocol (DPP)
229          * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and
230          * search for "Easy Connect" or "Device Provisioning Protocol specification".
231          */
232         public static final int DPP = 17;
233 
234         public static final String varName = "key_mgmt";
235 
236         public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP",
237                 "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP",
238                 "SAE", "OWE", "SUITE_B_192", "WPA_PSK_SHA256", "WPA_EAP_SHA256",
239                 "WAPI_PSK", "WAPI_CERT", "FILS_SHA256", "FILS_SHA384", "DPP" };
240     }
241 
242     /**
243      * Recognized security protocols.
244      */
245     public static class Protocol {
Protocol()246         private Protocol() { }
247 
248         /** WPA/IEEE 802.11i/D3.0
249          * @deprecated Due to security and performance limitations, use of WPA-1 networks
250          * is discouraged. WPA-2 (RSN) should be used instead. */
251         @Deprecated
252         public static final int WPA = 0;
253         /** RSN WPA2/WPA3/IEEE 802.11i */
254         public static final int RSN = 1;
255         /** HS2.0 r2 OSEN
256          * @hide
257          */
258         public static final int OSEN = 2;
259 
260         /**
261          * WAPI Protocol
262          */
263         public static final int WAPI = 3;
264 
265         /** @hide */
266         @Retention(RetentionPolicy.SOURCE)
267         @IntDef(value = {WPA, RSN, OSEN, WAPI})
268         public @interface ProtocolScheme {};
269 
270         public static final String varName = "proto";
271 
272         public static final String[] strings = { "WPA", "RSN", "OSEN", "WAPI" };
273     }
274 
275     /**
276      * Recognized IEEE 802.11 authentication algorithms.
277      */
278     public static class AuthAlgorithm {
AuthAlgorithm()279         private AuthAlgorithm() { }
280 
281         /** Open System authentication (required for WPA/WPA2) */
282         public static final int OPEN = 0;
283         /** Shared Key authentication (requires static WEP keys)
284          * @deprecated Due to security and performance limitations, use of WEP networks
285          * is discouraged. */
286         @Deprecated
287         public static final int SHARED = 1;
288         /** LEAP/Network EAP (only used with LEAP) */
289         public static final int LEAP = 2;
290 
291         /** SAE (Used only for WPA3-Personal) */
292         public static final int SAE = 3;
293 
294         /** @hide */
295         @Retention(RetentionPolicy.SOURCE)
296         @IntDef(value = {OPEN, SHARED, LEAP, SAE})
297         public @interface AuthAlgorithmScheme {};
298 
299         public static final String varName = "auth_alg";
300 
301         public static final String[] strings = { "OPEN", "SHARED", "LEAP", "SAE" };
302     }
303 
304     /**
305      * Recognized pairwise ciphers for WPA.
306      */
307     public static class PairwiseCipher {
PairwiseCipher()308         private PairwiseCipher() { }
309 
310         /** Use only Group keys (deprecated) */
311         public static final int NONE = 0;
312         /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
313          * @deprecated Due to security and performance limitations, use of WPA-1 networks
314          * is discouraged. WPA-2 (RSN) should be used instead. */
315         @Deprecated
316         public static final int TKIP = 1;
317         /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
318         public static final int CCMP = 2;
319         /**
320          * AES in Galois/Counter Mode
321          */
322         public static final int GCMP_256 = 3;
323         /**
324          * SMS4 cipher for WAPI
325          */
326         public static final int SMS4 = 4;
327 
328         /**
329          * AES in Galois/Counter Mode with a 128-bit integrity key
330          */
331         public static final int GCMP_128 = 5;
332 
333         /** @hide */
334         @Retention(RetentionPolicy.SOURCE)
335         @IntDef(value = {NONE, TKIP, CCMP, GCMP_256, SMS4, GCMP_128})
336         public @interface PairwiseCipherScheme {};
337 
338         public static final String varName = "pairwise";
339 
340         public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256", "SMS4",
341                 "GCMP_128" };
342     }
343 
344     /**
345      * Recognized group ciphers.
346      * <pre>
347      * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
348      * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
349      * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
350      * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
351      * GCMP_256 = AES in Galois/Counter Mode
352      * </pre>
353      */
354     public static class GroupCipher {
GroupCipher()355         private GroupCipher() { }
356 
357         /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
358          * @deprecated Due to security and performance limitations, use of WEP networks
359          * is discouraged. */
360         @Deprecated
361         public static final int WEP40 = 0;
362         /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
363          * @deprecated Due to security and performance limitations, use of WEP networks
364          * is discouraged. */
365         @Deprecated
366         public static final int WEP104 = 1;
367         /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
368         public static final int TKIP = 2;
369         /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
370         public static final int CCMP = 3;
371         /** Hotspot 2.0 r2 OSEN
372          * @hide
373          */
374         public static final int GTK_NOT_USED = 4;
375         /**
376          * AES in Galois/Counter Mode
377          */
378         public static final int GCMP_256 = 5;
379         /**
380          * SMS4 cipher for WAPI
381          */
382         public static final int SMS4 = 6;
383         /**
384          * AES in Galois/Counter Mode with a 128-bit integrity key
385          */
386         public static final int GCMP_128 = 7;
387 
388         /** @hide */
389         @Retention(RetentionPolicy.SOURCE)
390         @IntDef(value = {WEP40, WEP104, TKIP, CCMP, GTK_NOT_USED, GCMP_256, SMS4, GCMP_128})
391         public @interface GroupCipherScheme {};
392 
393         public static final String varName = "group";
394 
395         public static final String[] strings =
396                 { /* deprecated */ "WEP40", /* deprecated */ "WEP104",
397                         "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256",
398                         "SMS4", "GCMP_128" };
399     }
400 
401     /**
402      * Recognized group management ciphers.
403      * <pre>
404      * BIP_CMAC_256 = Cipher-based Message Authentication Code 256 bits
405      * BIP_GMAC_128 = Galois Message Authentication Code 128 bits
406      * BIP_GMAC_256 = Galois Message Authentication Code 256 bits
407      * </pre>
408      */
409     public static class GroupMgmtCipher {
GroupMgmtCipher()410         private GroupMgmtCipher() { }
411 
412         /** CMAC-256 = Cipher-based Message Authentication Code */
413         public static final int BIP_CMAC_256 = 0;
414 
415         /** GMAC-128 = Galois Message Authentication Code */
416         public static final int BIP_GMAC_128 = 1;
417 
418         /** GMAC-256 = Galois Message Authentication Code */
419         public static final int BIP_GMAC_256 = 2;
420 
421         /** @hide */
422         @Retention(RetentionPolicy.SOURCE)
423         @IntDef(value = {BIP_CMAC_256, BIP_GMAC_128, BIP_GMAC_256})
424         public @interface GroupMgmtCipherScheme {};
425 
426         private static final String varName = "groupMgmt";
427 
428         /** @hide */
429         @SuppressLint("AllUpper")
430         public static final @NonNull String[] strings = { "BIP_CMAC_256",
431                 "BIP_GMAC_128", "BIP_GMAC_256"};
432     }
433 
434     /**
435      * Recognized suiteB ciphers.
436      * <pre>
437      * ECDHE_ECDSA
438      * ECDHE_RSA
439      * </pre>
440      * @hide
441      */
442     public static class SuiteBCipher {
SuiteBCipher()443         private SuiteBCipher() { }
444 
445         /** Diffie-Hellman with Elliptic Curve_ECDSA signature */
446         public static final int ECDHE_ECDSA = 0;
447 
448         /** Diffie-Hellman with_RSA signature */
449         public static final int ECDHE_RSA = 1;
450 
451         /** @hide */
452         @Retention(RetentionPolicy.SOURCE)
453         @IntDef(value = {ECDHE_ECDSA, ECDHE_RSA})
454         public @interface SuiteBCipherScheme {};
455 
456         private static final String varName = "SuiteB";
457 
458         /** @hide */
459         @SuppressLint("AllUpper")
460         public static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" };
461     }
462 
463     /** Possible status of a network configuration. */
464     public static class Status {
Status()465         private Status() { }
466 
467         /** this is the network we are currently connected to */
468         public static final int CURRENT = 0;
469         /** supplicant will not attempt to use this network */
470         public static final int DISABLED = 1;
471         /** supplicant will consider this network available for association */
472         public static final int ENABLED = 2;
473 
474         public static final String[] strings = { "current", "disabled", "enabled" };
475     }
476 
477     /** Security type for an open network. */
478     public static final int SECURITY_TYPE_OPEN = 0;
479     /** Security type for a WEP network. */
480     public static final int SECURITY_TYPE_WEP = 1;
481     /** Security type for a PSK network. */
482     public static final int SECURITY_TYPE_PSK = 2;
483     /** Security type for an EAP network. */
484     public static final int SECURITY_TYPE_EAP = 3;
485     /** Security type for an SAE network. */
486     public static final int SECURITY_TYPE_SAE = 4;
487     /**
488      * Security type for a WPA3-Enterprise in 192-bit security network.
489      * This is the same as {@link #SECURITY_TYPE_EAP_SUITE_B} and uses the same value.
490      */
491     public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT = 5;
492     /**
493      * Security type for a WPA3-Enterprise in 192-bit security network.
494      * @deprecated Use the {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT} constant
495      * (which is the same value).
496      */
497     @Deprecated
498     public static final int SECURITY_TYPE_EAP_SUITE_B =
499             SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT;
500     /** Security type for an OWE network. */
501     public static final int SECURITY_TYPE_OWE = 6;
502     /** Security type for a WAPI PSK network. */
503     public static final int SECURITY_TYPE_WAPI_PSK = 7;
504     /** Security type for a WAPI Certificate network. */
505     public static final int SECURITY_TYPE_WAPI_CERT = 8;
506     /** Security type for a WPA3-Enterprise network. */
507     public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE = 9;
508     /**
509      * Security type for an OSEN network.
510      * @hide
511      */
512     public static final int SECURITY_TYPE_OSEN = 10;
513     /**
514      * Security type for a Passpoint R1/R2 network.
515      * Passpoint R1/R2 uses Enterprise security, where TKIP and WEP are not allowed.
516      * @hide
517      */
518     public static final int SECURITY_TYPE_PASSPOINT_R1_R2 = 11;
519 
520     /**
521      * Security type for a Passpoint R3 network.
522      * Passpoint R3 uses Enterprise security, where TKIP and WEP are not allowed,
523      * and PMF must be set to Required.
524      * @hide
525      */
526     public static final int SECURITY_TYPE_PASSPOINT_R3 = 12;
527 
528     /** Security type for Easy Connect (DPP) network */
529     public static final int SECURITY_TYPE_DPP = 13;
530 
531     /**
532      * This is used for the boundary check and should be the same as the last type.
533      * @hide
534      */
535     public static final int SECURITY_TYPE_NUM = SECURITY_TYPE_DPP;
536 
537     /**
538      * Security types we support.
539      * @hide
540      */
541     @Retention(RetentionPolicy.SOURCE)
542     @IntDef(prefix = { "SECURITY_TYPE_" }, value = {
543             SECURITY_TYPE_OPEN,
544             SECURITY_TYPE_WEP,
545             SECURITY_TYPE_PSK,
546             SECURITY_TYPE_EAP,
547             SECURITY_TYPE_SAE,
548             SECURITY_TYPE_EAP_SUITE_B,
549             SECURITY_TYPE_OWE,
550             SECURITY_TYPE_WAPI_PSK,
551             SECURITY_TYPE_WAPI_CERT,
552             SECURITY_TYPE_EAP_WPA3_ENTERPRISE,
553             SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT,
554             SECURITY_TYPE_PASSPOINT_R1_R2,
555             SECURITY_TYPE_PASSPOINT_R3,
556             SECURITY_TYPE_DPP,
557     })
558     public @interface SecurityType {}
559 
560     private static final String[] SECURITY_TYPE_NAMES = {
561         "open", "wep", "wpa2-psk", "wpa2-enterprise",
562         "wpa3-sae", "wpa3 enterprise 192-bit", "owe",
563         "wapi-psk", "wapi-cert", "wpa3 enterprise",
564         "wpa3 enterprise 192-bit", "passpoint r1/r2",
565         "passpoint r3", "dpp"};
566 
567     private List<SecurityParams> mSecurityParamsList = new ArrayList<>();
568 
updateLegacySecurityParams()569     private void updateLegacySecurityParams() {
570         if (mSecurityParamsList.isEmpty()) return;
571         mSecurityParamsList.get(0).updateLegacyWifiConfiguration(this);
572     }
573 
574     /**
575      * Set the various security params to correspond to the provided security type.
576      * This is accomplished by setting the various BitSets exposed in WifiConfiguration.
577      * <br>
578      * This API would clear existing security types and add a default one.
579      *
580      * Before calling this API with {@link #SECURITY_TYPE_DPP} as securityType,
581      * call {@link WifiManager#isEasyConnectDppAkmSupported() to know whether this security type is
582      * supported or not.
583      *
584      * @param securityType One of the following security types:
585      * {@link #SECURITY_TYPE_OPEN},
586      * {@link #SECURITY_TYPE_WEP},
587      * {@link #SECURITY_TYPE_PSK},
588      * {@link #SECURITY_TYPE_EAP},
589      * {@link #SECURITY_TYPE_SAE},
590      * {@link #SECURITY_TYPE_OWE},
591      * {@link #SECURITY_TYPE_WAPI_PSK},
592      * {@link #SECURITY_TYPE_WAPI_CERT},
593      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
594      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
595      * {@link #SECURITY_TYPE_DPP},
596      */
setSecurityParams(@ecurityType int securityType)597     public void setSecurityParams(@SecurityType int securityType) {
598         // Clear existing data.
599         mSecurityParamsList.clear();
600         addSecurityParams(securityType);
601     }
602 
603     /**
604      * Set security params by the given key management mask.
605      *
606      * @param givenAllowedKeyManagement the given allowed key management mask.
607      * @hide
608      */
setSecurityParams(@onNull BitSet givenAllowedKeyManagement)609     public void setSecurityParams(@NonNull BitSet givenAllowedKeyManagement) {
610         if (givenAllowedKeyManagement == null) {
611             throw new IllegalArgumentException("Invalid allowed key management mask.");
612         }
613         // Clear existing data.
614         mSecurityParamsList.clear();
615         allowedKeyManagement = (BitSet) givenAllowedKeyManagement.clone();
616         convertLegacyFieldsToSecurityParamsIfNeeded();
617     }
618 
619     /**
620      * Add the various security params.
621      * <br>
622      * This API would clear existing security types and add a default one.
623      * @hide
624      */
setSecurityParams(SecurityParams params)625     public void setSecurityParams(SecurityParams params) {
626         // Clear existing data.
627         mSecurityParamsList.clear();
628         addSecurityParams(params);
629     }
630 
631     /**
632      * Set the security params by the given security params list.
633      *
634      * This will overwrite existing security params list directly.
635      *
636      * @param securityParamsList the desired security params list.
637      * @hide
638      */
setSecurityParams(@onNull List<SecurityParams> securityParamsList)639     public void setSecurityParams(@NonNull List<SecurityParams> securityParamsList) {
640         if (securityParamsList == null || securityParamsList.isEmpty()) {
641             throw new IllegalArgumentException("An empty security params list is invalid.");
642         }
643         mSecurityParamsList = new ArrayList<>(securityParamsList.size());
644         securityParamsList.forEach(p -> mSecurityParamsList.add(new SecurityParams(p)));
645         updateLegacySecurityParams();
646     }
647 
648     /**
649      * Add the various security params to correspond to the provided security type.
650      * This is accomplished by setting the various BitSets exposed in WifiConfiguration.
651      *
652      * @param securityType One of the following security types:
653      * {@link #SECURITY_TYPE_OPEN},
654      * {@link #SECURITY_TYPE_WEP},
655      * {@link #SECURITY_TYPE_PSK},
656      * {@link #SECURITY_TYPE_EAP},
657      * {@link #SECURITY_TYPE_SAE},
658      * {@link #SECURITY_TYPE_OWE},
659      * {@link #SECURITY_TYPE_WAPI_PSK},
660      * {@link #SECURITY_TYPE_WAPI_CERT},
661      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
662      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
663      * {@link #SECURITY_TYPE_DPP},
664      *
665      * @hide
666      */
addSecurityParams(@ecurityType int securityType)667     public void addSecurityParams(@SecurityType int securityType) {
668         // This ensures that there won't be duplicate security types.
669         for (SecurityParams params : mSecurityParamsList) {
670             if (params.isSecurityType(securityType)) {
671                 throw new IllegalArgumentException("duplicate security type " + securityType);
672             }
673         }
674         addSecurityParams(SecurityParams.createSecurityParamsBySecurityType(securityType));
675     }
676 
677     /** @hide */
addSecurityParams(@onNull SecurityParams newParams)678     public void addSecurityParams(@NonNull SecurityParams newParams) {
679         // This ensures that there won't be duplicate security types.
680         for (SecurityParams params : mSecurityParamsList) {
681             if (params.isSameSecurityType(newParams)) {
682                 throw new IllegalArgumentException("duplicate security params " + newParams);
683             }
684         }
685         if (!mSecurityParamsList.isEmpty()) {
686             if (newParams.isEnterpriseSecurityType() && !isEnterprise()) {
687                 throw new IllegalArgumentException(
688                         "An enterprise security type cannot be added to a personal configuation.");
689             }
690             if (!newParams.isEnterpriseSecurityType() && isEnterprise()) {
691                 throw new IllegalArgumentException(
692                         "A personal security type cannot be added to an enterprise configuation.");
693             }
694             if (newParams.isOpenSecurityType() && !isOpenNetwork()) {
695                 throw new IllegalArgumentException(
696                         "An open security type cannot be added to a non-open configuation.");
697             }
698             if (!newParams.isOpenSecurityType() && isOpenNetwork()) {
699                 throw new IllegalArgumentException(
700                         "A non-open security type cannot be added to an open configuation.");
701             }
702             if (newParams.isSecurityType(SECURITY_TYPE_OSEN)) {
703                 throw new IllegalArgumentException(
704                         "An OSEN security type must be the only one type.");
705             }
706         }
707         mSecurityParamsList.add(new SecurityParams(newParams));
708         updateLegacySecurityParams();
709     }
710 
isWpa3EnterpriseConfiguration()711     private boolean isWpa3EnterpriseConfiguration() {
712         if (!allowedKeyManagement.get(KeyMgmt.WPA_EAP_SHA256)
713                 && !allowedKeyManagement.get(KeyMgmt.WPA_EAP)
714                 && !allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
715             return false;
716         }
717         if (!requirePmf) return false;
718         // Only RSN protocol is set.
719         if (allowedProtocols.cardinality() > 1) return false;
720         if (!allowedProtocols.get(Protocol.RSN)) return false;
721         // TKIP is not allowed.
722         if (allowedPairwiseCiphers.get(PairwiseCipher.TKIP)) return false;
723         if (allowedGroupCiphers.get(GroupCipher.TKIP)) return false;
724         return true;
725     }
726 
727     /**
728      * Return whether the configuration is a WPA-Personal network
729      * @hide
730      */
isWpaPersonalOnlyConfiguration()731     public boolean isWpaPersonalOnlyConfiguration() {
732         return isSecurityType(SECURITY_TYPE_PSK)
733                 && allowedProtocols.get(Protocol.WPA)
734                 && !allowedProtocols.get(Protocol.RSN);
735     }
736 
737     /**
738      * If there is no security params, generate one according to legacy fields.
739      * @hide
740      */
convertLegacyFieldsToSecurityParamsIfNeeded()741     public void convertLegacyFieldsToSecurityParamsIfNeeded() {
742         if (!mSecurityParamsList.isEmpty()) return;
743         if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {
744             setSecurityParams(SECURITY_TYPE_WAPI_CERT);
745         } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) {
746             setSecurityParams(SECURITY_TYPE_WAPI_PSK);
747         } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
748             setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
749         } else if (allowedKeyManagement.get(KeyMgmt.DPP)) {
750             setSecurityParams(SECURITY_TYPE_DPP);
751         } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
752             setSecurityParams(SECURITY_TYPE_OWE);
753         } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
754             setSecurityParams(SECURITY_TYPE_SAE);
755         } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) {
756             setSecurityParams(SECURITY_TYPE_OSEN);
757         } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)
758                 || allowedKeyManagement.get(KeyMgmt.WPA_PSK_SHA256)
759                 || allowedKeyManagement.get(KeyMgmt.FT_PSK)) {
760             setSecurityParams(SECURITY_TYPE_PSK);
761         } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
762                 || allowedKeyManagement.get(KeyMgmt.FT_EAP)
763                 || allowedKeyManagement.get(KeyMgmt.IEEE8021X)
764                 || allowedKeyManagement.get(KeyMgmt.WPA_EAP_SHA256)
765                 || allowedKeyManagement.get(KeyMgmt.FILS_SHA256)
766                 || allowedKeyManagement.get(KeyMgmt.FILS_SHA384)) {
767             if (isWpa3EnterpriseConfiguration()) {
768                 setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
769             } else {
770                 setSecurityParams(SECURITY_TYPE_EAP);
771             }
772         } else if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
773             setSecurityParams(SECURITY_TYPE_PSK);
774         } else if (allowedKeyManagement.get(KeyMgmt.DPP)) {
775             setSecurityParams(SECURITY_TYPE_DPP);
776         } else if (allowedKeyManagement.get(KeyMgmt.NONE)) {
777             if (hasWepKeys()) {
778                 setSecurityParams(SECURITY_TYPE_WEP);
779             } else {
780                 setSecurityParams(SECURITY_TYPE_OPEN);
781             }
782         } else {
783             setSecurityParams(SECURITY_TYPE_OPEN);
784         }
785     }
786 
787     /**
788      * Disable the various security params to correspond to the provided security type.
789      * This is accomplished by setting the various BitSets exposed in WifiConfiguration.
790      *
791      * @param securityType One of the following security types:
792      * {@link #SECURITY_TYPE_OPEN},
793      * {@link #SECURITY_TYPE_WEP},
794      * {@link #SECURITY_TYPE_PSK},
795      * {@link #SECURITY_TYPE_EAP},
796      * {@link #SECURITY_TYPE_SAE},
797      * {@link #SECURITY_TYPE_OWE},
798      * {@link #SECURITY_TYPE_WAPI_PSK},
799      * {@link #SECURITY_TYPE_WAPI_CERT},
800      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
801      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
802      * {@link #SECURITY_TYPE_DPP},
803      *
804      * @hide
805      */
setSecurityParamsEnabled(@ecurityType int securityType, boolean enable)806     public void setSecurityParamsEnabled(@SecurityType int securityType, boolean enable) {
807         for (SecurityParams p : mSecurityParamsList) {
808             if (p.isSecurityType(securityType)) {
809                 p.setEnabled(enable);
810                 return;
811             }
812         }
813     }
814 
815     /**
816      * Set whether a type is added by auto-upgrade.
817      *
818      * @param securityType One of the following security types:
819      * {@link #SECURITY_TYPE_OPEN},
820      * {@link #SECURITY_TYPE_WEP},
821      * {@link #SECURITY_TYPE_PSK},
822      * {@link #SECURITY_TYPE_EAP},
823      * {@link #SECURITY_TYPE_SAE},
824      * {@link #SECURITY_TYPE_OWE},
825      * {@link #SECURITY_TYPE_WAPI_PSK},
826      * {@link #SECURITY_TYPE_WAPI_CERT},
827      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
828      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
829      *
830      * @hide
831      */
setSecurityParamsIsAddedByAutoUpgrade( @ecurityType int securityType, boolean isAddedByAutoUpgrade)832     public void setSecurityParamsIsAddedByAutoUpgrade(
833             @SecurityType int securityType, boolean isAddedByAutoUpgrade) {
834         for (SecurityParams p : mSecurityParamsList) {
835             if (p.isSecurityType(securityType)) {
836                 p.setIsAddedByAutoUpgrade(isAddedByAutoUpgrade);
837                 return;
838             }
839         }
840     }
841 
842     /**
843      * Get the specific security param.
844      *
845      * @param securityType One of the following security types:
846      * {@link #SECURITY_TYPE_OPEN},
847      * {@link #SECURITY_TYPE_WEP},
848      * {@link #SECURITY_TYPE_PSK},
849      * {@link #SECURITY_TYPE_EAP},
850      * {@link #SECURITY_TYPE_SAE},
851      * {@link #SECURITY_TYPE_OWE},
852      * {@link #SECURITY_TYPE_WAPI_PSK},
853      * {@link #SECURITY_TYPE_WAPI_CERT},
854      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
855      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
856      * {@link #SECURITY_TYPE_DPP},
857      *
858      * @return the copy of specific security params if found; otherwise null.
859      * @hide
860      */
getSecurityParams(@ecurityType int securityType)861     public @Nullable SecurityParams getSecurityParams(@SecurityType int securityType) {
862         for (SecurityParams p : mSecurityParamsList) {
863             if (p.isSecurityType(securityType)) {
864                 return new SecurityParams(p);
865             }
866         }
867         return null;
868     }
869 
870     /**
871      * Indicate whether this configuration is the specific security type.
872      *
873      * @param securityType One of the following security types:
874      * {@link #SECURITY_TYPE_OPEN},
875      * {@link #SECURITY_TYPE_WEP},
876      * {@link #SECURITY_TYPE_PSK},
877      * {@link #SECURITY_TYPE_EAP},
878      * {@link #SECURITY_TYPE_SAE},
879      * {@link #SECURITY_TYPE_OWE},
880      * {@link #SECURITY_TYPE_WAPI_PSK},
881      * {@link #SECURITY_TYPE_WAPI_CERT},
882      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
883      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
884      * {@link #SECURITY_TYPE_DPP},
885      *
886      * @return true if there is a security params matches the type.
887      * @hide
888      */
isSecurityType(@ecurityType int securityType)889     public boolean isSecurityType(@SecurityType int securityType) {
890         for (SecurityParams p : mSecurityParamsList) {
891             if (p.isSecurityType(securityType)) {
892                 return true;
893             }
894         }
895         return false;
896     }
897 
898     /**
899      * Get the security params list of this configuration.
900      *
901      * The returning list is a priority list, the first is the lowest priority and default one.
902      *
903      * @return this list of security params.
904      * @hide
905      */
getSecurityParamsList()906     public List<SecurityParams> getSecurityParamsList() {
907         return Collections.unmodifiableList(mSecurityParamsList);
908     }
909 
910     /**
911      * Get the default params which is the same as the legacy fields.
912      *
913      * @return the default security params.
914      * @hide
915      */
getDefaultSecurityParams()916     public @NonNull SecurityParams getDefaultSecurityParams() {
917         return new SecurityParams(mSecurityParamsList.get(0));
918     }
919 
920     /**
921      * Enable the support of Fast Initial Link Set-up (FILS).
922      *
923      * FILS can be applied to all security types.
924      * @param enableFilsSha256 Enable FILS SHA256.
925      * @param enableFilsSha384 Enable FILS SHA256.
926      * @hide
927      */
enableFils(boolean enableFilsSha256, boolean enableFilsSha384)928     public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) {
929         mSecurityParamsList.forEach(params ->
930                 params.enableFils(enableFilsSha256, enableFilsSha384));
931         updateLegacySecurityParams();
932     }
933 
934     /**
935      * Indicate FILS SHA256 is enabled.
936      *
937      * @return true if FILS SHA256 is enabled.
938      * @hide
939      */
isFilsSha256Enabled()940     public boolean isFilsSha256Enabled() {
941         for (SecurityParams p : mSecurityParamsList) {
942             if (p.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA256)) {
943                 return true;
944             }
945         }
946         return false;
947     }
948 
949     /**
950      * Indicate FILS SHA384 is enabled.
951      *
952      * @return true if FILS SHA384 is enabled.
953      * @hide
954      */
isFilsSha384Enabled()955     public boolean isFilsSha384Enabled() {
956         for (SecurityParams p : mSecurityParamsList) {
957             if (p.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA384)) {
958                 return true;
959             }
960         }
961         return false;
962     }
963 
964     /**
965      * Enable Suite-B ciphers.
966      *
967      * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support.
968      * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support.
969      * @hide
970      */
enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa)971     public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) {
972         for (SecurityParams p : mSecurityParamsList) {
973             if (p.isSecurityType(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT)) {
974                 p.enableSuiteBCiphers(enableEcdheEcdsa, enableEcdheRsa);
975                 updateLegacySecurityParams();
976                 return;
977             }
978         }
979     }
980 
981     /**
982      * Indicate ECDHE_ECDSA is enabled.
983      *
984      * @return true if enabled.
985      * @hide
986      */
isSuiteBCipherEcdheEcdsaEnabled()987     public boolean isSuiteBCipherEcdheEcdsaEnabled() {
988         for (SecurityParams p : mSecurityParamsList) {
989             if (p.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_ECDSA)) {
990                 return true;
991             }
992         }
993         return false;
994     }
995 
996     /**
997      * Indicate ECDHE_RSA is enabled.
998      *
999      * @return true if enabled.
1000      * @hide
1001      */
isSuiteBCipherEcdheRsaEnabled()1002     public boolean isSuiteBCipherEcdheRsaEnabled() {
1003         for (SecurityParams p : mSecurityParamsList) {
1004             if (p.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_RSA)) {
1005                 return true;
1006             }
1007         }
1008         return false;
1009     }
1010 
1011     /**
1012      * Set SAE Hash-toElement only mode enabled.
1013      * Before calling this API, call {@link WifiManager#isWpa3SaeH2eSupported()
1014      * to know whether WPA3 SAE Hash-toElement is supported or not.
1015      *
1016      * @param enable true if enabled; false otherwise.
1017      * @hide
1018      */
enableSaeH2eOnlyMode(boolean enable)1019     public void enableSaeH2eOnlyMode(boolean enable) {
1020         for (SecurityParams p : mSecurityParamsList) {
1021             if (p.isSecurityType(SECURITY_TYPE_SAE)) {
1022                 p.enableSaeH2eOnlyMode(enable);
1023                 return;
1024             }
1025         }
1026     }
1027 
1028     /**
1029      * Set SAE Public-Key only mode enabled.
1030      * Before calling this API, call {@link WifiManager#isWpa3SaePkSupported()
1031      * to know whether WPA3 SAE Public-Key is supported or not.
1032      *
1033      * @param enable true if enabled; false otherwise.
1034      * @hide
1035      */
enableSaePkOnlyMode(boolean enable)1036     public void enableSaePkOnlyMode(boolean enable) {
1037         for (SecurityParams p : mSecurityParamsList) {
1038             if (p.isSecurityType(SECURITY_TYPE_SAE)) {
1039                 p.enableSaePkOnlyMode(enable);
1040                 return;
1041             }
1042         }
1043     }
1044 
1045     /** @hide */
1046     public static final int UNKNOWN_UID = -1;
1047 
1048     /**
1049      * The ID number that the supplicant uses to identify this
1050      * network configuration entry. This must be passed as an argument
1051      * to most calls into the supplicant.
1052      */
1053     public int networkId;
1054 
1055     // TODO (b/235236813): Remove this field and use quality network selection status instead.
1056     /**
1057      * The current status of this network configuration entry.
1058      * @see Status
1059      */
1060     public int status;
1061 
1062     /**
1063      * The network's SSID. Can either be a UTF-8 string,
1064      * which must be enclosed in double quotation marks
1065      * (e.g., {@code "MyNetwork"}), or a string of
1066      * hex digits, which are not enclosed in quotes
1067      * (e.g., {@code 01a243f405}).
1068      */
1069     public String SSID;
1070 
1071     /**
1072      * When set, this network configuration entry should only be used when
1073      * associating with the AP having the specified BSSID. The value is
1074      * a string in the format of an Ethernet MAC address, e.g.,
1075      * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
1076      */
1077     public String BSSID;
1078 
1079     private List<MacAddress> mBssidAllowlist;
1080 
1081     private byte[] mEncryptedPreSharedKey;
1082     private byte[] mEncryptedPreSharedKeyIv;
1083     private boolean mHasPreSharedKeyChanged;
1084 
1085     /**
1086      * Set a list of BSSIDs to control if this network configuration entry should be used to
1087      * associate an AP.
1088      * <ul>
1089      * <li>If set with {@code null}, then there are no restrictions on the connection. The
1090      * configuration will associate to any AP.</li>
1091      * <li>If set to an empty list then the configuration will not associate to any AP.</li>
1092      * <li>If set to a non-empty list then the configuration will only associate to APs whose BSSID
1093      * is on the list.</li>
1094      * </ul>
1095      * @param bssidAllowlist A list of {@link MacAddress} representing the BSSID of APs,
1096      * {@code null} to allow all BSSIDs (no restriction).
1097      * @hide
1098      */
1099     @SystemApi
setBssidAllowlist(@ullable List<MacAddress> bssidAllowlist)1100     public void setBssidAllowlist(@Nullable List<MacAddress> bssidAllowlist) {
1101         if (bssidAllowlist == null) {
1102             mBssidAllowlist = null;
1103             return;
1104         }
1105         mBssidAllowlist = new ArrayList<>(bssidAllowlist);
1106     }
1107 
1108     /**
1109      * Get a list of BSSIDs specified on this network configuration entry, set by
1110      * {@link #setBssidAllowlist(List)}.
1111      * @return A list of {@link MacAddress} representing BSSID to allow associate, {@code null} for
1112      * allowing all BSSIDs (no restriction).
1113      * @hide
1114      */
1115     @SuppressLint("NullableCollection")
1116     @SystemApi
1117     @Nullable
getBssidAllowlist()1118     public List<MacAddress> getBssidAllowlist() {
1119         if (mBssidAllowlist == null) {
1120             return null;
1121         }
1122         return new ArrayList<>(mBssidAllowlist);
1123     }
1124 
1125     /**
1126      * @hide
1127      */
getBssidAllowlistInternal()1128     public List<MacAddress> getBssidAllowlistInternal() {
1129         return mBssidAllowlist;
1130     }
1131 
1132     /** @hide */
1133     @Retention(RetentionPolicy.SOURCE)
1134     @IntDef(prefix = {"AP_BAND_"}, value = {
1135             AP_BAND_2GHZ,
1136             AP_BAND_5GHZ,
1137             AP_BAND_ANY})
1138     public @interface ApBand {}
1139 
1140     /**
1141      * 2GHz band.
1142      * @hide
1143      */
1144     public static final int AP_BAND_2GHZ = 0;
1145 
1146     /**
1147      * 5GHz band.
1148      * @hide
1149      */
1150     public static final int AP_BAND_5GHZ = 1;
1151 
1152     /**
1153      * 60GHz band
1154      * @hide
1155      */
1156     public static final int AP_BAND_60GHZ = 2;
1157 
1158     /**
1159      * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
1160      * operating country code and current radio conditions.
1161      * @hide
1162      */
1163     public static final int AP_BAND_ANY = -1;
1164 
1165     /**
1166      * The band which the AP resides on.
1167      * One of {@link #AP_BAND_2GHZ}, {@link #AP_BAND_5GHZ}, or {@link #AP_BAND_ANY}.
1168      * By default, {@link #AP_BAND_2GHZ} is chosen.
1169      *
1170      * @hide
1171      */
1172     @UnsupportedAppUsage
1173     @ApBand
1174     public int apBand = AP_BAND_2GHZ;
1175 
1176     /**
1177      * The channel which AP resides on,currently, US only
1178      * 2G  1-11
1179      * 5G  36,40,44,48,149,153,157,161,165
1180      * 0 - find a random available channel according to the apBand
1181      * @hide
1182      */
1183     @UnsupportedAppUsage
1184     public int apChannel = 0;
1185 
1186     /**
1187      * Pre-shared key for use with WPA-PSK. Either an ASCII string enclosed in
1188      * double quotation marks (e.g., {@code "abcdefghij"} for PSK passphrase or
1189      * a string of 64 hex digits for raw PSK.
1190      * <p/>
1191      * When the value of this key is read, the actual key is
1192      * not returned, just a "*" if the key has a value, or the null
1193      * string otherwise.
1194      */
1195     public String preSharedKey;
1196 
1197     /**
1198      * Four WEP keys. For each of the four values, provide either an ASCII
1199      * string enclosed in double quotation marks (e.g., {@code "abcdef"})
1200      * or a string of hex digits (e.g., {@code 0102030405}).
1201      * <p/>
1202      * When the value of one of these keys is read, the actual key is
1203      * not returned, just a "*" if the key has a value, or the null
1204      * string otherwise.
1205      * @deprecated Due to security and performance limitations, use of WEP networks
1206      * is discouraged.
1207      */
1208     @Deprecated
1209     public String[] wepKeys;
1210 
1211     /** Default WEP key index, ranging from 0 to 3.
1212      * @deprecated Due to security and performance limitations, use of WEP networks
1213      * is discouraged. */
1214     @Deprecated
1215     public int wepTxKeyIndex;
1216 
1217     /**
1218      * Priority determines the preference given to a network by {@code wpa_supplicant}
1219      * when choosing an access point with which to associate.
1220      * @deprecated This field does not exist anymore.
1221      */
1222     @Deprecated
1223     public int priority;
1224 
1225     /**
1226      * The deletion priority of this configuration.
1227      *
1228      * Deletion priority is a non-negative value (default 0) indicating the priority for deletion
1229      * when auto-pruning the amount of saved configurations. Networks with a lower value will be
1230      * pruned before networks with a higher value.
1231      */
1232     private int mDeletionPriority;
1233 
1234     /**
1235      * Sets the deletion priority of this configuration.
1236      *
1237      * Deletion priority is a non-negative value (default 0) indicating the priority for deletion
1238      * when auto-pruning the amount of saved configurations. Networks with a lower value will be
1239      * pruned before networks with a higher value.
1240      *
1241      * @param priority non-negative deletion priority
1242      * @hide
1243      */
1244     @SystemApi
setDeletionPriority(int priority)1245     public void setDeletionPriority(int priority) throws IllegalArgumentException {
1246         if (priority < 0) {
1247             throw new IllegalArgumentException("Deletion priority must be non-negative");
1248         }
1249         mDeletionPriority = priority;
1250     }
1251 
1252     /**
1253      * Returns the deletion priority of this configuration.
1254      *
1255      * Deletion priority is a non-negative value (default 0) indicating the priority for deletion
1256      * when auto-pruning the amount of saved configurations. Networks with a lower value will be
1257      * pruned before networks with a higher value.
1258      *
1259      * @hide
1260      */
1261     @SystemApi
getDeletionPriority()1262     public int getDeletionPriority() {
1263         return mDeletionPriority;
1264     }
1265 
1266     /**
1267      * This is a network that does not broadcast its SSID, so an
1268      * SSID-specific probe request must be used for scans.
1269      */
1270     public boolean hiddenSSID;
1271 
1272     /**
1273      * True if the network requires Protected Management Frames (PMF), false otherwise.
1274      * @hide
1275      */
1276     @SystemApi
1277     public boolean requirePmf;
1278 
1279     /**
1280      * Update identifier, for Passpoint network.
1281      * @hide
1282      */
1283     public String updateIdentifier;
1284 
1285     /**
1286      * The set of key management protocols supported by this configuration.
1287      * See {@link KeyMgmt} for descriptions of the values.
1288      * Defaults to WPA-PSK WPA-EAP.
1289      */
1290     @NonNull
1291     public BitSet allowedKeyManagement;
1292     /**
1293      * The set of security protocols supported by this configuration.
1294      * See {@link Protocol} for descriptions of the values.
1295      * Defaults to WPA RSN.
1296      */
1297     @NonNull
1298     public BitSet allowedProtocols;
1299     /**
1300      * The set of authentication protocols supported by this configuration.
1301      * See {@link AuthAlgorithm} for descriptions of the values.
1302      * Defaults to automatic selection.
1303      */
1304     @NonNull
1305     public BitSet allowedAuthAlgorithms;
1306     /**
1307      * The set of pairwise ciphers for WPA supported by this configuration.
1308      * See {@link PairwiseCipher} for descriptions of the values.
1309      * Defaults to CCMP TKIP.
1310      */
1311     @NonNull
1312     public BitSet allowedPairwiseCiphers;
1313     /**
1314      * The set of group ciphers supported by this configuration.
1315      * See {@link GroupCipher} for descriptions of the values.
1316      * Defaults to CCMP TKIP WEP104 WEP40.
1317      */
1318     @NonNull
1319     public BitSet allowedGroupCiphers;
1320     /**
1321      * The set of group management ciphers supported by this configuration.
1322      * See {@link GroupMgmtCipher} for descriptions of the values.
1323      */
1324     @NonNull
1325     public BitSet allowedGroupManagementCiphers;
1326     /**
1327      * The set of SuiteB ciphers supported by this configuration.
1328      * To be used for WPA3-Enterprise mode. Set automatically by the framework based on the
1329      * certificate type that is used in this configuration.
1330      */
1331     @NonNull
1332     public BitSet allowedSuiteBCiphers;
1333     /**
1334      * The enterprise configuration details specifying the EAP method,
1335      * certificates and other settings associated with the EAP.
1336      */
1337     public WifiEnterpriseConfig enterpriseConfig;
1338 
1339     /**
1340      * Fully qualified domain name of a Passpoint configuration
1341      */
1342     public String FQDN;
1343 
1344     /**
1345      * Name of Passpoint credential provider
1346      */
1347     public String providerFriendlyName;
1348 
1349     /**
1350      * Flag indicating if this network is provided by a home Passpoint provider or a roaming
1351      * Passpoint provider.  This flag will be {@code true} if this network is provided by
1352      * a home Passpoint provider and {@code false} if is provided by a roaming Passpoint provider
1353      * or is a non-Passpoint network.
1354      */
1355     public boolean isHomeProviderNetwork;
1356 
1357     /**
1358      * Roaming Consortium Id list for Passpoint credential; identifies a set of networks where
1359      * Passpoint credential will be considered valid
1360      */
1361     public long[] roamingConsortiumIds;
1362 
1363     /**
1364      * True if this network configuration is visible to and usable by other users on the
1365      * same device, false otherwise.
1366      *
1367      * @hide
1368      */
1369     @SystemApi
1370     public boolean shared;
1371 
1372     /**
1373      * @hide
1374      */
1375     @NonNull
1376     @UnsupportedAppUsage
1377     private IpConfiguration mIpConfiguration;
1378 
1379     /**
1380      * dhcp server MAC address if known
1381      * @hide
1382      */
1383     public String dhcpServer;
1384 
1385     /**
1386      * default Gateway MAC address if known
1387      * @hide
1388      */
1389     @UnsupportedAppUsage
1390     public String defaultGwMacAddress;
1391 
1392     /**
1393      * last time we connected, this configuration had validated internet access
1394      * @hide
1395      */
1396     @UnsupportedAppUsage
1397     public boolean validatedInternetAccess;
1398 
1399     /**
1400      * The number of beacon intervals between Delivery Traffic Indication Maps (DTIM)
1401      * This value is populated from scan results that contain Beacon Frames, which are infrequent.
1402      * The value is not guaranteed to be set or current (Although it SHOULDNT change once set)
1403      * Valid values are from 1 - 255. Initialized here as 0, use this to check if set.
1404      * @hide
1405      */
1406     public int dtimInterval = 0;
1407 
1408     /**
1409      * Flag indicating if this configuration represents a legacy Passpoint configuration
1410      * (Release N or older).  This is used for migrating Passpoint configuration from N to O.
1411      * This will no longer be needed after O.
1412      * @hide
1413      */
1414     public boolean isLegacyPasspointConfig = false;
1415     /**
1416      * Uid of app creating the configuration
1417      * @hide
1418      */
1419     @SystemApi
1420     public int creatorUid;
1421 
1422     /**
1423      * Uid of last app issuing a connection related command
1424      * @hide
1425      */
1426     @SystemApi
1427     public int lastConnectUid;
1428 
1429     /**
1430      * Uid of last app modifying the configuration
1431      * @hide
1432      */
1433     @SystemApi
1434     public int lastUpdateUid;
1435 
1436     /**
1437      * Universal name for app creating the configuration
1438      *    see {@link PackageManager#getNameForUid(int)}
1439      * @hide
1440      */
1441     @SystemApi
1442     public String creatorName;
1443 
1444     /**
1445      * Universal name for app updating the configuration
1446      *    see {@link PackageManager#getNameForUid(int)}
1447      * @hide
1448      */
1449     @SystemApi
1450     public String lastUpdateName;
1451 
1452     /**
1453      * The carrier ID identifies the operator who provides this network configuration.
1454      *    see {@link TelephonyManager#getSimCarrierId()}
1455      * @hide
1456      */
1457     @SystemApi
1458     public int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
1459 
1460     /**
1461      * The subscription ID identifies the SIM card for which this network configuration is valid.
1462      * See {@link SubscriptionInfo#getSubscriptionId()}
1463      * @hide
1464      */
1465     @SystemApi
1466     public int subscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1467 
1468     @Nullable
1469     private ParcelUuid mSubscriptionGroup = null;
1470 
1471     /**
1472      * Auto-join is allowed by user for this network.
1473      * Default true.
1474      * @hide
1475      */
1476     @SystemApi
1477     public boolean allowAutojoin = true;
1478 
1479     /**
1480      * Wi-Fi7 is enabled by user for this network.
1481      * Default true.
1482      */
1483     private boolean mWifi7Enabled = true;
1484 
1485     /**
1486      * @hide
1487      */
setIpProvisioningTimedOut(boolean value)1488     public void setIpProvisioningTimedOut(boolean value) {
1489         mIpProvisioningTimedOut = value;
1490     }
1491 
1492     /**
1493      * @hide
1494      */
isIpProvisioningTimedOut()1495     public boolean isIpProvisioningTimedOut() {
1496         return mIpProvisioningTimedOut;
1497     }
1498 
1499     /** @hide **/
1500     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1501     public static int INVALID_RSSI = -127;
1502 
1503     /**
1504      * Number of reports indicating no Internet Access
1505      * @hide
1506      */
1507     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1508     public int numNoInternetAccessReports;
1509 
1510     /**
1511      * The WiFi configuration had no internet access the last time we connected to it.
1512      * @hide
1513      */
1514     @SystemApi
hasNoInternetAccess()1515     public boolean hasNoInternetAccess() {
1516         return getNetworkSelectionStatus().hasEverConnected() && !validatedInternetAccess;
1517     }
1518 
1519     /**
1520      * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a
1521      * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to
1522      * this configuration and selects "don't ask again".
1523      * @hide
1524      */
1525     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1526     public boolean noInternetAccessExpected;
1527 
1528     /**
1529      * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a
1530      * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to
1531      * this configuration and selects "don't ask again".
1532      * @hide
1533      */
1534     @SystemApi
isNoInternetAccessExpected()1535     public boolean isNoInternetAccessExpected() {
1536         return noInternetAccessExpected;
1537     }
1538 
1539     /**
1540      * This Wifi configuration is expected for OSU(Online Sign Up) of Passpoint Release 2.
1541      * @hide
1542      */
1543     public boolean osu;
1544 
1545     /**
1546      * Last time the system was connected to this configuration represented as the difference,
1547      * measured in milliseconds, between the last connected time and midnight, January 1, 1970 UTC.
1548      * <P>
1549      * Note that this information is only in memory will be cleared (reset to 0) for all
1550      * WifiConfiguration(s) after a reboot.
1551      * @hide
1552      */
1553     @SuppressLint("MutableBareField")
1554     @SystemApi
1555     public long lastConnected;
1556 
1557     /**
1558      * Last time the system was disconnected to this configuration.
1559      * @hide
1560      */
1561     public long lastDisconnected;
1562 
1563     /**
1564      * Last time this configuration was updated or created.
1565      * Note: This field only exists in-memory and is not persisted in WifiConfigStore.xml for
1566      *       privacy reasons.
1567      * @hide
1568      */
1569     public long lastUpdated;
1570 
1571     /**
1572      * Number of reboots since this config was last used (either connected or updated).
1573      * @hide
1574      */
1575     @SuppressLint("MutableBareField")
1576     @SystemApi
1577     public int numRebootsSinceLastUse;
1578 
1579     /**
1580      * Set if the configuration was self added by the framework
1581      * This boolean is cleared if we get a connect/save/ update or
1582      * any wifiManager command that indicate the user interacted with the configuration
1583      * since we will now consider that the configuration belong to him.
1584      * @deprecated only kept for @UnsupportedAppUsage
1585      * @hide
1586      */
1587     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1588     public boolean selfAdded;
1589 
1590     /**
1591      * Peer WifiConfiguration this WifiConfiguration was added for
1592      * @hide
1593      */
1594     public String peerWifiConfiguration;
1595 
1596     /**
1597      * Indicate that a WifiConfiguration is temporary and should not be saved
1598      * nor considered by AutoJoin.
1599      * @hide
1600      */
1601     public boolean ephemeral;
1602 
1603     /**
1604      * Indicate that a WifiConfiguration is temporary and should not be saved
1605      * nor considered by AutoJoin.
1606      * @hide
1607      */
1608     @SystemApi
isEphemeral()1609     public boolean isEphemeral() {
1610       return ephemeral;
1611     }
1612 
1613     /**
1614      * Indicate whether the network is trusted or not. Networks are considered trusted
1615      * if the user explicitly allowed this network connection.
1616      * This bit can be used by suggestion network, see
1617      * {@link WifiNetworkSuggestion.Builder#setUntrusted(boolean)}
1618      * @hide
1619      */
1620     public boolean trusted;
1621 
1622     /**
1623      * Indicate whether the network is oem paid or not. Networks are considered oem paid
1624      * if the corresponding connection is only available to system apps.
1625      *
1626      * This bit can only be used by suggestion network, see
1627      * {@link WifiNetworkSuggestion.Builder#setOemPaid(boolean)}
1628      * @hide
1629      */
1630     public boolean oemPaid;
1631 
1632 
1633     /**
1634      * Indicate whether the network is oem private or not. Networks are considered oem private
1635      * if the corresponding connection is only available to system apps.
1636      *
1637      * This bit can only be used by suggestion network, see
1638      * {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)}
1639      * @hide
1640      */
1641     public boolean oemPrivate;
1642 
1643     /**
1644      * Indicate whether or not the network is a carrier merged network.
1645      * This bit can only be used by suggestion network, see
1646      * {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)}
1647      * @hide
1648      */
1649     @SystemApi
1650     public boolean carrierMerged;
1651 
1652     /**
1653      * True if this Wifi configuration is created from a {@link WifiNetworkSuggestion},
1654      * false otherwise.
1655      *
1656      * @hide
1657      */
1658     @SystemApi
1659     public boolean fromWifiNetworkSuggestion;
1660 
1661     /**
1662      * True if this Wifi configuration is created from a {@link WifiNetworkSpecifier},
1663      * false otherwise.
1664      *
1665      * @hide
1666      */
1667     @SystemApi
1668     public boolean fromWifiNetworkSpecifier;
1669 
1670     /**
1671      * True if the creator of this configuration has expressed that it
1672      * should be considered metered, false otherwise.
1673      *
1674      * @see #isMetered(WifiConfiguration, WifiInfo)
1675      *
1676      * @hide
1677      */
1678     @SystemApi
1679     public boolean meteredHint;
1680 
1681     /**
1682      * True if this configuration is intended to be repeater enabled to expand coverage.
1683      */
1684     private boolean mIsRepeaterEnabled;
1685 
1686     /**
1687      * @hide
1688      */
1689     private boolean mIpProvisioningTimedOut;
1690 
1691     /**
1692      * Sets if this configuration is intended to be repeater enabled for expanded coverage.
1693      *
1694      * @param isRepeaterEnabled true if this network is intended to be repeater enabled,
1695      *        false otherwise.
1696      *
1697      * This request is only accepted if the caller is holding
1698      * {@link android.Manifest.permission#NETWORK_SETTINGS}.
1699      *
1700      * @hide
1701      */
1702     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
1703     @SystemApi
setRepeaterEnabled(boolean isRepeaterEnabled)1704     public void setRepeaterEnabled(boolean isRepeaterEnabled) {
1705         mIsRepeaterEnabled = isRepeaterEnabled;
1706     }
1707 
1708     /**
1709      * Returns if this configuration is intended to be repeater enabled for expanded coverage.
1710      *
1711      * @return true if this network is intended to be repeater enabled, false otherwise.
1712      *
1713      * @hide
1714      */
1715     @SystemApi
isRepeaterEnabled()1716     public boolean isRepeaterEnabled() {
1717         return mIsRepeaterEnabled;
1718     }
1719 
1720     /**
1721      * Indicate whether the network is restricted or not.
1722      *
1723      * This bit can only be used by suggestion network, see
1724      * {@link WifiNetworkSuggestion.Builder#setRestricted(boolean)}
1725      * @hide
1726      */
1727     public boolean restricted;
1728 
1729     /** @hide */
1730     @Retention(RetentionPolicy.SOURCE)
1731     @IntDef(prefix = {"METERED_OVERRIDE_"}, value = {
1732             METERED_OVERRIDE_NONE,
1733             METERED_OVERRIDE_METERED,
1734             METERED_OVERRIDE_NOT_METERED})
1735     public @interface MeteredOverride {}
1736 
1737     /**
1738      * No metered override.
1739      * @hide
1740      */
1741     @SystemApi
1742     public static final int METERED_OVERRIDE_NONE = 0;
1743     /**
1744      * Override network to be metered.
1745      * @hide
1746      */
1747     @SystemApi
1748     public static final int METERED_OVERRIDE_METERED = 1;
1749     /**
1750      * Override network to be unmetered.
1751      * @hide
1752      */
1753     @SystemApi
1754     public static final int METERED_OVERRIDE_NOT_METERED = 2;
1755 
1756     /**
1757      * Indicates if the end user has expressed an explicit opinion about the
1758      * meteredness of this network, such as through the Settings app.
1759      * This value is one of {@link #METERED_OVERRIDE_NONE}, {@link #METERED_OVERRIDE_METERED},
1760      * or {@link #METERED_OVERRIDE_NOT_METERED}.
1761      * <p>
1762      * This should always override any values from {@link #meteredHint} or
1763      * {@link WifiInfo#getMeteredHint()}.
1764      *
1765      * By default this field is set to {@link #METERED_OVERRIDE_NONE}.
1766      *
1767      * @see #isMetered(WifiConfiguration, WifiInfo)
1768      * @hide
1769      */
1770     @SystemApi
1771     @MeteredOverride
1772     public int meteredOverride = METERED_OVERRIDE_NONE;
1773 
1774     /**
1775      * Blend together all the various opinions to decide if the given network
1776      * should be considered metered or not.
1777      *
1778      * @hide
1779      */
1780     @SystemApi
isMetered(@ullable WifiConfiguration config, @Nullable WifiInfo info)1781     public static boolean isMetered(@Nullable WifiConfiguration config, @Nullable WifiInfo info) {
1782         boolean metered = false;
1783         if (info != null && info.getMeteredHint()) {
1784             metered = true;
1785         }
1786         if (config != null && config.meteredHint) {
1787             metered = true;
1788         }
1789         if (config != null
1790                 && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) {
1791             metered = true;
1792         }
1793         if (config != null
1794                 && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) {
1795             metered = false;
1796         }
1797         return metered;
1798     }
1799 
1800     /** Check whether wep keys exist. */
hasWepKeys()1801     private boolean hasWepKeys() {
1802         if (wepKeys == null) return false;
1803         for (int i = 0; i < wepKeys.length; i++) {
1804             if (wepKeys[i] != null) {
1805                 return true;
1806             }
1807         }
1808         return false;
1809     }
1810 
1811     /**
1812      * Returns true if this WiFi config is for an Open or Enhanced Open network.
1813      * @hide
1814      */
isOpenNetwork()1815     public boolean isOpenNetwork() {
1816         if (hasWepKeys()) {
1817             return false;
1818         }
1819         for (SecurityParams p : mSecurityParamsList) {
1820             if (!p.isOpenSecurityType()) {
1821                 return false;
1822             }
1823         }
1824         return true;
1825     }
1826 
1827     /**
1828      * Setting this value will force scan results associated with this configuration to
1829      * be included in the bucket of networks that are externally scored.
1830      * If not set, associated scan results will be treated as legacy saved networks and
1831      * will take precedence over networks in the scored category.
1832      * @hide
1833      */
1834     @SystemApi
1835     public boolean useExternalScores;
1836 
1837     /**
1838      * Number of time the scorer overrode a the priority based choice, when comparing two
1839      * WifiConfigurations, note that since comparing WifiConfiguration happens very often
1840      * potentially at every scan, this number might become very large, even on an idle
1841      * system.
1842      * @hide
1843      */
1844     @SystemApi
1845     public int numScorerOverride;
1846 
1847     /**
1848      * Number of time the scorer overrode a the priority based choice, and the comparison
1849      * triggered a network switch
1850      * @hide
1851      */
1852     @SystemApi
1853     public int numScorerOverrideAndSwitchedNetwork;
1854 
1855     /**
1856      * Number of times we associated to this configuration.
1857      * @hide
1858      */
1859     @SystemApi
1860     public int numAssociation;
1861 
1862     /** @hide */
1863     @Retention(RetentionPolicy.SOURCE)
1864     @IntDef(prefix = {"RANDOMIZATION_"}, value = {
1865             RANDOMIZATION_NONE,
1866             RANDOMIZATION_PERSISTENT,
1867             RANDOMIZATION_NON_PERSISTENT,
1868             RANDOMIZATION_AUTO})
1869     public @interface MacRandomizationSetting {}
1870 
1871     /**
1872      * Use factory MAC when connecting to this network
1873      */
1874     public static final int RANDOMIZATION_NONE = 0;
1875 
1876     /**
1877      * Generate a randomized MAC once and reuse it for all connections to this network
1878      */
1879     public static final int RANDOMIZATION_PERSISTENT = 1;
1880 
1881     /**
1882      * Use a randomly generated MAC address for connections to this network.
1883      * This option does not persist the randomized MAC address.
1884      */
1885     public static final int RANDOMIZATION_NON_PERSISTENT = 2;
1886 
1887     /**
1888      * Let the wifi framework automatically decide the MAC randomization strategy.
1889      */
1890     public static final int RANDOMIZATION_AUTO = 3;
1891 
1892     /**
1893      * Level of MAC randomization for this network.
1894      * One of {@link #RANDOMIZATION_NONE}, {@link #RANDOMIZATION_AUTO},
1895      * {@link #RANDOMIZATION_PERSISTENT} or {@link #RANDOMIZATION_NON_PERSISTENT}.
1896      * By default this field is set to {@link #RANDOMIZATION_AUTO}.
1897      * @hide
1898      */
1899     @SystemApi
1900     @MacRandomizationSetting
1901     public int macRandomizationSetting = RANDOMIZATION_AUTO;
1902 
1903     /**
1904      * Set the MAC randomization setting for this network.
1905      * <p>
1906      * Caller must satify one of the following conditions:
1907      * </p>
1908      * <ul>
1909      * <li>Have {@code android.Manifest.permission#NETWORK_SETTINGS} permission.</li>
1910      * <li>Have {@code android.Manifest.permission#NETWORK_SETUP_WIZARD} permission.</li>
1911      * <li>Be in Demo Mode.</li>
1912      * <li>Be the creator adding or updating a passpoint network.</li>
1913      * <li>Be an admin updating their own network.</li>
1914      * </ul>
1915      */
setMacRandomizationSetting(@acRandomizationSetting int macRandomizationSetting)1916     public void setMacRandomizationSetting(@MacRandomizationSetting int macRandomizationSetting) {
1917         this.macRandomizationSetting = macRandomizationSetting;
1918     }
1919 
1920     /**
1921      * Get the MAC randomization setting for this network.
1922      */
getMacRandomizationSetting()1923     public @MacRandomizationSetting int getMacRandomizationSetting() {
1924         return this.macRandomizationSetting;
1925     }
1926 
1927     /**
1928      * Randomized MAC address to use with this particular network
1929      * @hide
1930      */
1931     @NonNull
1932     private MacAddress mRandomizedMacAddress;
1933 
1934     /**
1935      * The wall clock time of when |mRandomizedMacAddress| should be re-randomized in non-persistent
1936      * MAC randomization mode.
1937      * @hide
1938      */
1939     public long randomizedMacExpirationTimeMs = 0;
1940 
1941     /**
1942      * The wall clock time of when |mRandomizedMacAddress| is last modified.
1943      * @hide
1944      */
1945     public long randomizedMacLastModifiedTimeMs = 0;
1946 
1947     /**
1948      * Checks if the given MAC address can be used for Connected Mac Randomization
1949      * by verifying that it is non-null, unicast, locally assigned, and not default mac.
1950      * @param mac MacAddress to check
1951      * @return true if mac is good to use
1952      * @hide
1953      */
isValidMacAddressForRandomization(MacAddress mac)1954     public static boolean isValidMacAddressForRandomization(MacAddress mac) {
1955         return mac != null && !MacAddressUtils.isMulticastAddress(mac) && mac.isLocallyAssigned()
1956                 && !MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS).equals(mac);
1957     }
1958 
1959     /**
1960      * Returns MAC address set to be the local randomized MAC address.
1961      * Depending on user preference, the device may or may not use the returned MAC address for
1962      * connections to this network.
1963      * <p>
1964      * Information is restricted to Device Owner, Profile Owner, and Carrier apps
1965      * (which will only obtain addresses for configurations which they create). Other callers
1966      * will receive a default "02:00:00:00:00:00" MAC address.
1967      */
getRandomizedMacAddress()1968     public @NonNull MacAddress getRandomizedMacAddress() {
1969         return mRandomizedMacAddress;
1970     }
1971 
1972     /**
1973      * @param mac MacAddress to change into
1974      * @hide
1975      */
setRandomizedMacAddress(@onNull MacAddress mac)1976     public void setRandomizedMacAddress(@NonNull MacAddress mac) {
1977         if (mac == null) {
1978             Log.e(TAG, "setRandomizedMacAddress received null MacAddress.");
1979             return;
1980         }
1981         mRandomizedMacAddress = mac;
1982     }
1983 
1984     private boolean mIsSendDhcpHostnameEnabled = true;
1985 
1986     /**
1987      * Set whether to send the hostname of the device to this network's DHCP server.
1988      *
1989      * @param enabled {@code true} to send the hostname during DHCP,
1990      *             {@code false} to not send the hostname during DHCP.
1991      * @hide
1992      */
1993     @RequiresPermission(anyOf = {
1994             android.Manifest.permission.NETWORK_SETTINGS,
1995             android.Manifest.permission.NETWORK_SETUP_WIZARD})
1996     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
1997     @SystemApi
setSendDhcpHostnameEnabled(boolean enabled)1998     public void setSendDhcpHostnameEnabled(boolean enabled) {
1999         mIsSendDhcpHostnameEnabled = enabled;
2000     }
2001 
2002     /**
2003      * Whether to send the hostname of the device to this network's DHCP server.
2004      * @hide
2005      */
2006     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
2007     @SystemApi
isSendDhcpHostnameEnabled()2008     public boolean isSendDhcpHostnameEnabled() {
2009         return mIsSendDhcpHostnameEnabled;
2010     }
2011 
2012     /**
2013      * This network supports DPP AKM and the device is configured to
2014      * onboard peer enrollee devices with {@link #SECURITY_TYPE_DPP}
2015      * @hide
2016      */
2017     private boolean mIsDppConfigurator;
2018 
2019     /**
2020      * Private elliptic curve key used by DPP Configurator to generate other DPP Keys
2021      * for DPP-AKM based network configuration.
2022      * @hide
2023      */
2024     private byte[] mDppPrivateEcKey;
2025 
2026     /**
2027      * Signed DPP connector. The connector is used by a pair of Enrollee devices to establish
2028      * a security association using the DPP Introduction Protocol.
2029      * @hide
2030      */
2031     private byte[] mDppConnector;
2032 
2033     /**
2034      * The public signing key of the DPP configurator.
2035      * @hide
2036      */
2037     private byte[] mDppCSignKey;
2038 
2039     /**
2040      * DPP network access key (own private key)
2041      * @hide
2042      */
2043     private byte[] mDppNetAccessKey;
2044 
2045     /**
2046      * Set DPP Connection keys which are used for network access.
2047      * This is required for SECURITY_TYPE_DPP network connection.
2048      * @hide
2049      */
setDppConnectionKeys(byte[] connector, byte[] cSignKey, byte[] netAccessKey)2050     public void setDppConnectionKeys(byte[] connector, byte[] cSignKey, byte[] netAccessKey) {
2051         if (connector == null || cSignKey == null || netAccessKey == null) {
2052             Log.e(TAG, "One of DPP key is null");
2053             return;
2054         }
2055         mDppConnector = connector.clone();
2056         mDppCSignKey = cSignKey.clone();
2057         mDppNetAccessKey = netAccessKey.clone();
2058     }
2059 
2060     /**
2061      * Allow this profile as configurable DPP profile.
2062      * This is required to allow SECURITY_TYPE_DPP profile to be eligible for Configuration
2063      * of DPP-Enrollees.
2064      * @hide
2065      */
setDppConfigurator(byte[] ecKey)2066     public void setDppConfigurator(byte[] ecKey) {
2067         if (ecKey != null) {
2068             mDppPrivateEcKey = ecKey.clone();
2069             mIsDppConfigurator = true;
2070         }
2071     }
2072 
2073     /**
2074      * To check if this WifiConfiguration supports configuring a peer Enrollee device with
2075      * SECURITY_TYPE_DPP
2076      */
isDppConfigurator()2077     public boolean isDppConfigurator() {
2078         return mIsDppConfigurator;
2079     }
2080 
2081     /**
2082      * Get private elliptic curve key used by DPP Configurator to generate other DPP Keys
2083      * for DPP-AKM based network configuration.
2084      * @hide
2085      */
2086     @SystemApi
getDppPrivateEcKey()2087     @NonNull public byte[] getDppPrivateEcKey() {
2088         return mDppPrivateEcKey.clone();
2089     }
2090 
2091     /**
2092      * Get DPP signed connector. The connector is used by a pair of Enrollee devices to establish
2093      * a security association using the DPP Introduction Protocol.
2094      * @hide
2095      */
2096     @SystemApi
getDppConnector()2097     @NonNull public byte[] getDppConnector() {
2098         return mDppConnector.clone();
2099     }
2100 
2101     /**
2102      * Get public signing key of the DPP configurator. This key is used by provisioned devices
2103      * to verify Connectors of other devices are signed by the same Configurator. The configurator
2104      * derives and sets the C-sign-key in each DPP Configuration object.
2105      *
2106      * @hide
2107      */
2108     @SystemApi
getDppCSignKey()2109     @NonNull public byte[] getDppCSignKey() {
2110         return mDppCSignKey.clone();
2111     }
2112 
2113     /**
2114      * Get DPP network access key. Own private key used to generate common secret, PMK.
2115      * @hide
2116      */
2117     @SystemApi
getDppNetAccessKey()2118     @NonNull public byte[] getDppNetAccessKey() {
2119         return mDppNetAccessKey.clone();
2120     }
2121 
2122     /** @hide
2123      * Boost given to RSSI on a home network for the purpose of calculating the score
2124      * This adds stickiness to home networks, as defined by:
2125      * - less than 4 known BSSIDs
2126      * - PSK only
2127      * - TODO: add a test to verify that all BSSIDs are behind same gateway
2128      ***/
2129     public static final int HOME_NETWORK_RSSI_BOOST = 5;
2130 
2131     /**
2132      * This class is used to contain all the information and API used for quality network selection.
2133      * @hide
2134      */
2135     @SystemApi
2136     public static class NetworkSelectionStatus {
2137         /** @hide */
2138         @Retention(RetentionPolicy.SOURCE)
2139         @IntDef(prefix = "NETWORK_SELECTION_",
2140                 value = {
2141                 NETWORK_SELECTION_ENABLED,
2142                 NETWORK_SELECTION_TEMPORARY_DISABLED,
2143                 NETWORK_SELECTION_PERMANENTLY_DISABLED})
2144         public @interface NetworkEnabledStatus {}
2145         /**
2146          * This network will be considered as a potential candidate to connect to during network
2147          * selection.
2148          */
2149         public static final int NETWORK_SELECTION_ENABLED = 0;
2150         /**
2151          * This network was temporary disabled. May be re-enabled after a time out.
2152          */
2153         public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1;
2154         /**
2155          * This network was permanently disabled.
2156          */
2157         public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2;
2158         /**
2159          * Maximum Network selection status
2160          * @hide
2161          */
2162         public static final int NETWORK_SELECTION_STATUS_MAX = 3;
2163 
2164         /**
2165          * Quality network selection status String (for debug purpose). Use Quality network
2166          * selection status value as index to extec the corresponding debug string
2167          * @hide
2168          */
2169         public static final String[] QUALITY_NETWORK_SELECTION_STATUS = {
2170                 "NETWORK_SELECTION_ENABLED",
2171                 "NETWORK_SELECTION_TEMPORARY_DISABLED",
2172                 "NETWORK_SELECTION_PERMANENTLY_DISABLED"};
2173 
2174         /** @hide */
2175         @Retention(RetentionPolicy.SOURCE)
2176         @IntDef(prefix = "DISABLED_", value = {
2177                 DISABLED_NONE,
2178                 DISABLED_ASSOCIATION_REJECTION,
2179                 DISABLED_AUTHENTICATION_FAILURE,
2180                 DISABLED_DHCP_FAILURE,
2181                 DISABLED_NO_INTERNET_TEMPORARY,
2182                 DISABLED_AUTHENTICATION_NO_CREDENTIALS,
2183                 DISABLED_NO_INTERNET_PERMANENT,
2184                 DISABLED_BY_WIFI_MANAGER,
2185                 DISABLED_BY_WRONG_PASSWORD,
2186                 DISABLED_AUTHENTICATION_NO_SUBSCRIPTION,
2187                 DISABLED_AUTHENTICATION_PRIVATE_EAP_ERROR,
2188                 DISABLED_NETWORK_NOT_FOUND,
2189                 DISABLED_CONSECUTIVE_FAILURES,
2190                 DISABLED_UNWANTED_LOW_RSSI,
2191                 DISABLED_REPEATED_NUD_FAILURES})
2192         public @interface NetworkSelectionDisableReason {}
2193 
2194         // Quality Network disabled reasons
2195         /** Default value. Means not disabled. */
2196         public static final int DISABLED_NONE = 0;
2197         /**
2198          * The starting index for network selection disabled reasons.
2199          * @hide
2200          */
2201         public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1;
2202         /** This network is temporarily disabled because of multiple association rejections. */
2203         public static final int DISABLED_ASSOCIATION_REJECTION = 1;
2204         /** This network is temporarily disabled because of multiple authentication failure. */
2205         public static final int DISABLED_AUTHENTICATION_FAILURE = 2;
2206         /** This network is temporarily disabled because of multiple DHCP failure. */
2207         public static final int DISABLED_DHCP_FAILURE = 3;
2208         /** This network is temporarily disabled because it has no Internet access. */
2209         public static final int DISABLED_NO_INTERNET_TEMPORARY = 4;
2210         /** This network is permanently disabled due to absence of user credentials */
2211         public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 5;
2212         /**
2213          * This network is permanently disabled because it has no Internet access and the user does
2214          * not want to stay connected.
2215          */
2216         public static final int DISABLED_NO_INTERNET_PERMANENT = 6;
2217         /** This network is permanently disabled due to WifiManager disabling it explicitly. */
2218         public static final int DISABLED_BY_WIFI_MANAGER = 7;
2219         /** This network is permanently disabled due to wrong password. */
2220         public static final int DISABLED_BY_WRONG_PASSWORD = 8;
2221         /** This network is permanently disabled because service is not subscribed. */
2222         public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9;
2223         /** This network is disabled due to provider-specific (private) EAP failure. */
2224         public static final int DISABLED_AUTHENTICATION_PRIVATE_EAP_ERROR = 10;
2225         /**
2226          * This network is disabled because supplicant failed to find a network in scan result
2227          * which matches the network requested by framework for connection
2228          * (including network capabilities).
2229          */
2230         public static final int DISABLED_NETWORK_NOT_FOUND = 11;
2231         /**
2232          * This code is used to disable a network when a high number of consecutive connection
2233          * failures are detected. The exact reasons of why these consecutive failures occurred is
2234          * included but not limited to the reasons described by failure codes above.
2235          */
2236         public static final int DISABLED_CONSECUTIVE_FAILURES = 12;
2237         /**
2238          * This code is used to disable a network when a security params is disabled
2239          * by the transition disable indication.
2240          */
2241         public static final int DISABLED_TRANSITION_DISABLE_INDICATION = 13;
2242         /**
2243          * This network is temporarily disabled because of unwanted network under sufficient rssi.
2244          */
2245         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
2246         public static final int DISABLED_UNWANTED_LOW_RSSI = 14;
2247         /**
2248          * This network is temporarily disabled due to repeated IP reachability failures.
2249          * @hide
2250          */
2251         public static final int DISABLED_REPEATED_NUD_FAILURES = 15;
2252         /**
2253          * All other disable reasons should be strictly less than this value.
2254          * @hide
2255          */
2256         public static final int NETWORK_SELECTION_DISABLED_MAX = 16;
2257 
2258         /**
2259          * Get an integer that is equal to the maximum integer value of all the
2260          * DISABLED_* reasons
2261          * e.g. {@link #DISABLED_NONE}, {@link #DISABLED_ASSOCIATION_REJECTION}, etc.
2262          *
2263          * All DISABLED_* constants will be contiguous in the range
2264          * 0, 1, 2, 3, ..., getMaxNetworkSelectionDisableReasons()
2265          *
2266          * <br />
2267          * For example, this can be used to iterate through all the network selection
2268          * disable reasons like so:
2269          * <pre>{@code
2270          * for (int reason = 0; reason <= getMaxNetworkSelectionDisableReasons(); reason++) {
2271          *     ...
2272          * }
2273          * }</pre>
2274          */
getMaxNetworkSelectionDisableReason()2275         public static int getMaxNetworkSelectionDisableReason() {
2276             return NETWORK_SELECTION_DISABLED_MAX - 1;
2277         }
2278 
2279         /**
2280          * Contains info about disable reasons.
2281          * @hide
2282          */
2283         public static final class DisableReasonInfo {
2284             /**
2285              * A special constant which indicates the network should be permanently disabled.
2286              * @hide
2287              */
2288             public static final int PERMANENT_DISABLE_TIMEOUT = -1;
2289             /**
2290              * String representation for the disable reason.
2291              * Note that these strings are persisted in
2292              * {@link
2293              * com.android.server.wifi.util.XmlUtil.NetworkSelectionStatusXmlUtil#writeToXml},
2294              * so do not change the string values to maintain backwards compatibility.
2295              */
2296             public final String mReasonStr;
2297             /**
2298              * Network Selection disable reason threshold, used to debounce network failures before
2299              * we disable them.
2300              */
2301             public final int mDisableThreshold;
2302             /**
2303              * Network Selection disable timeout for the error. After the timeout milliseconds,
2304              * enable the network again.
2305              * If this is set to PERMANENT_DISABLE_TIMEOUT, the network will be permanently disabled
2306              * until the next time the user manually connects to it.
2307              */
2308             public final int mDisableTimeoutMillis;
2309 
2310             /**
2311              * Constructor
2312              * @param reasonStr string representation of the error
2313              * @param disableThreshold number of failures before we disable the network
2314              * @param disableTimeoutMillis the timeout, in milliseconds, before we re-enable the
2315              *                             network after disabling it
2316              */
DisableReasonInfo(String reasonStr, int disableThreshold, int disableTimeoutMillis)2317             public DisableReasonInfo(String reasonStr, int disableThreshold,
2318                     int disableTimeoutMillis) {
2319                 mReasonStr = reasonStr;
2320                 mDisableThreshold = disableThreshold;
2321                 mDisableTimeoutMillis = disableTimeoutMillis;
2322             }
2323         }
2324 
2325         /**
2326          * Quality network selection disable reason infos.
2327          * @hide
2328          */
2329         public static final SparseArray<DisableReasonInfo> DISABLE_REASON_INFOS =
2330                 buildDisableReasonInfos();
2331 
buildDisableReasonInfos()2332         private static SparseArray<DisableReasonInfo> buildDisableReasonInfos() {
2333             SparseArray<DisableReasonInfo> reasons = new SparseArray<>();
2334 
2335             // Note that some of these disable thresholds are overridden in
2336             // WifiBlocklistMonitor#loadCustomConfigsForDisableReasonInfos using overlays.
2337             // TODO(b/180148727): For a few of these disable reasons, we provide defaults here
2338             //  and in the overlay XML, which is confusing. Clean this up so we only define the
2339             //  default in one place.
2340 
2341             reasons.append(DISABLED_NONE,
2342                     new DisableReasonInfo(
2343                             // Note that these strings are persisted in
2344                             // XmlUtil.NetworkSelectionStatusXmlUtil#writeToXml,
2345                             // so do not change the string values to maintain backwards
2346                             // compatibility.
2347                             "NETWORK_SELECTION_ENABLE",
2348                             -1,
2349                             0));
2350 
2351             reasons.append(DISABLED_ASSOCIATION_REJECTION,
2352                     new DisableReasonInfo(
2353                             // Note that there is a space at the end of this string. Cannot fix
2354                             // since this string is persisted.
2355                             "NETWORK_SELECTION_DISABLED_ASSOCIATION_REJECTION ",
2356                             3,
2357                             5 * 60 * 1000));
2358 
2359             reasons.append(DISABLED_AUTHENTICATION_FAILURE,
2360                     new DisableReasonInfo(
2361                             "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE",
2362                             3,
2363                             5 * 60 * 1000));
2364 
2365             reasons.append(DISABLED_DHCP_FAILURE,
2366                     new DisableReasonInfo(
2367                             "NETWORK_SELECTION_DISABLED_DHCP_FAILURE",
2368                             2,
2369                             5 * 60 * 1000));
2370 
2371             reasons.append(DISABLED_NO_INTERNET_TEMPORARY,
2372                     new DisableReasonInfo(
2373                             "NETWORK_SELECTION_DISABLED_NO_INTERNET_TEMPORARY",
2374                             1,
2375                             10 * 60 * 1000));
2376 
2377             reasons.append(DISABLED_AUTHENTICATION_NO_CREDENTIALS,
2378                     new DisableReasonInfo(
2379                             "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS",
2380                             3,
2381                             DisableReasonInfo.PERMANENT_DISABLE_TIMEOUT));
2382 
2383             reasons.append(DISABLED_NO_INTERNET_PERMANENT,
2384                     new DisableReasonInfo(
2385                             "NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT",
2386                             1,
2387                             DisableReasonInfo.PERMANENT_DISABLE_TIMEOUT));
2388 
2389             reasons.append(DISABLED_BY_WIFI_MANAGER,
2390                     new DisableReasonInfo(
2391                             "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER",
2392                             1,
2393                             DisableReasonInfo.PERMANENT_DISABLE_TIMEOUT));
2394 
2395             reasons.append(DISABLED_BY_WRONG_PASSWORD,
2396                     new DisableReasonInfo(
2397                             "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD",
2398                             1,
2399                             DisableReasonInfo.PERMANENT_DISABLE_TIMEOUT));
2400 
2401             reasons.append(DISABLED_AUTHENTICATION_NO_SUBSCRIPTION,
2402                     new DisableReasonInfo(
2403                             "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_SUBSCRIPTION",
2404                             1,
2405                             DisableReasonInfo.PERMANENT_DISABLE_TIMEOUT));
2406 
2407             reasons.append(DISABLED_AUTHENTICATION_PRIVATE_EAP_ERROR,
2408                     new DisableReasonInfo(
2409                             "NETWORK_SELECTION_DISABLED_AUTHENTICATION_PRIVATE_EAP_ERROR",
2410                             1,
2411                             DisableReasonInfo.PERMANENT_DISABLE_TIMEOUT));
2412 
2413             reasons.append(DISABLED_NETWORK_NOT_FOUND,
2414                     new DisableReasonInfo(
2415                             "NETWORK_SELECTION_DISABLED_NETWORK_NOT_FOUND",
2416                             2,
2417                             5 * 60 * 1000));
2418 
2419             reasons.append(DISABLED_CONSECUTIVE_FAILURES,
2420                     new DisableReasonInfo("NETWORK_SELECTION_DISABLED_CONSECUTIVE_FAILURES",
2421                             1,
2422                             5 * 60 * 1000));
2423 
2424             reasons.append(DISABLED_TRANSITION_DISABLE_INDICATION,
2425                     new DisableReasonInfo(
2426                             "NETWORK_SELECTION_DISABLED_TRANSITION_DISABLE_INDICATION",
2427                             1,
2428                             DisableReasonInfo.PERMANENT_DISABLE_TIMEOUT));
2429 
2430             reasons.append(DISABLED_UNWANTED_LOW_RSSI,
2431                     new DisableReasonInfo("NETWORK_SELECTION_DISABLED_UNWANTED_LOW_RSSI",
2432                             1,
2433                             30 * 1000));
2434             reasons.append(DISABLED_REPEATED_NUD_FAILURES,
2435                     new DisableReasonInfo("NETWORK_SELECTION_DISABLED_REPEATED_NUD_FAILURES",
2436                             1,
2437                             15 * 60 * 1000));
2438             return reasons;
2439         }
2440 
2441         /**
2442          * Get the {@link NetworkSelectionDisableReason} int code by its string value.
2443          * @return the NetworkSelectionDisableReason int code corresponding to the reason string,
2444          * or -1 if the reason string is unrecognized.
2445          * @hide
2446          */
2447         @NetworkSelectionDisableReason
getDisableReasonByString(@onNull String reasonString)2448         public static int getDisableReasonByString(@NonNull String reasonString) {
2449             for (int i = 0; i < DISABLE_REASON_INFOS.size(); i++) {
2450                 int key = DISABLE_REASON_INFOS.keyAt(i);
2451                 DisableReasonInfo value = DISABLE_REASON_INFOS.valueAt(i);
2452                 if (value != null && TextUtils.equals(reasonString, value.mReasonStr)) {
2453                     return key;
2454                 }
2455             }
2456             Log.e(TAG, "Unrecognized network disable reason: " + reasonString);
2457             return -1;
2458         }
2459 
2460         /**
2461          * Invalid time stamp for network selection disable
2462          * @hide
2463          */
2464         public static final long INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP = -1L;
2465 
2466         /**
2467          * This constant indicates the current configuration has connect choice set
2468          */
2469         private static final int CONNECT_CHOICE_EXISTS = 1;
2470 
2471         /**
2472          * This constant indicates the current configuration does not have connect choice set
2473          */
2474         private static final int CONNECT_CHOICE_NOT_EXISTS = -1;
2475 
2476         // fields for QualityNetwork Selection
2477         /**
2478          * Network selection status, should be in one of three status: enable, temporaily disabled
2479          * or permanently disabled
2480          */
2481         @NetworkEnabledStatus
2482         private int mStatus;
2483 
2484         /**
2485          * Reason for disable this network
2486          */
2487         @NetworkSelectionDisableReason
2488         private int mNetworkSelectionDisableReason;
2489 
2490         /**
2491          * Last time we temporarily disabled the configuration
2492          */
2493         private long mTemporarilyDisabledTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;
2494 
2495         private long mTemporarilyDisabledEndTime = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;
2496 
2497         /**
2498          * counter for each Network selection disable reason
2499          */
2500         private int[] mNetworkSeclectionDisableCounter = new int[NETWORK_SELECTION_DISABLED_MAX];
2501 
2502         /**
2503          * Connect Choice over this configuration
2504          *
2505          * When current wifi configuration is visible to the user but user explicitly choose to
2506          * connect to another network X, the another networks X's configure key will be stored here.
2507          * We will consider user has a preference of X over this network. And in the future,
2508          * network selection will always give X a higher preference over this configuration.
2509          * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP
2510          */
2511         private String mConnectChoice;
2512 
2513         /**
2514          * The RSSI when the user made the connectChoice.
2515          */
2516         private int mConnectChoiceRssi;
2517 
2518         /**
2519          * Used to cache the temporary candidate during the network selection procedure. It will be
2520          * kept updating once a new scan result has a higher score than current one
2521          */
2522         private ScanResult mCandidate;
2523 
2524         /**
2525          * Used to cache the score of the current temporary candidate during the network
2526          * selection procedure.
2527          */
2528         private int mCandidateScore;
2529 
2530         /**
2531          * Used to cache the select security params from the candidate.
2532          */
2533         private SecurityParams mCandidateSecurityParams;
2534 
2535         /**
2536          * Used to cache the last used security params for the candidate.
2537          */
2538         private SecurityParams mLastUsedSecurityParams;
2539 
2540         /**
2541          * Indicate whether this network is visible in latest Qualified Network Selection. This
2542          * means there is scan result found related to this Configuration and meet the minimum
2543          * requirement. The saved network need not join latest Qualified Network Selection. For
2544          * example, it is disabled. True means network is visible in latest Qualified Network
2545          * Selection and false means network is invisible
2546          */
2547         private boolean mSeenInLastQualifiedNetworkSelection;
2548 
2549         /**
2550          * Boolean indicating if we have ever successfully connected to this network.
2551          *
2552          * This value will be set to true upon a successful connection.
2553          * This value will be set to false if a previous value was not stored in the config or if
2554          * the credentials are updated (ex. a password change).
2555          */
2556         private boolean mHasEverConnected;
2557 
2558         /**
2559          * Boolean indicating if captive portal has never been detected on this network.
2560          *
2561          * This should be true by default, for newly created WifiConfigurations until a captive
2562          * portal is detected.
2563          */
2564         private boolean mHasNeverDetectedCaptivePortal = true;
2565 
2566 
2567         /**
2568          * Boolean tracking whether internet validation have ever completed successfully on this
2569          * WifiConfiguration.
2570          */
2571         private boolean mHasEverValidatedInternetAccess;
2572 
2573         /**
2574          * set whether this network is visible in latest Qualified Network Selection
2575          * @param seen value set to candidate
2576          * @hide
2577          */
setSeenInLastQualifiedNetworkSelection(boolean seen)2578         public void setSeenInLastQualifiedNetworkSelection(boolean seen) {
2579             mSeenInLastQualifiedNetworkSelection =  seen;
2580         }
2581 
2582         /**
2583          * get whether this network is visible in latest Qualified Network Selection
2584          * @return returns true -- network is visible in latest Qualified Network Selection
2585          *         false -- network is invisible in latest Qualified Network Selection
2586          * @hide
2587          */
getSeenInLastQualifiedNetworkSelection()2588         public boolean getSeenInLastQualifiedNetworkSelection() {
2589             return mSeenInLastQualifiedNetworkSelection;
2590         }
2591         /**
2592          * set the temporary candidate of current network selection procedure
2593          * @param scanCandidate {@link ScanResult} the candidate set to mCandidate
2594          * @hide
2595          */
setCandidate(ScanResult scanCandidate)2596         public void setCandidate(ScanResult scanCandidate) {
2597             mCandidate = scanCandidate;
2598         }
2599 
2600         /**
2601          * get the temporary candidate of current network selection procedure
2602          * @return  returns {@link ScanResult} temporary candidate of current network selection
2603          * procedure
2604          * @hide
2605          */
getCandidate()2606         public ScanResult getCandidate() {
2607             return mCandidate;
2608         }
2609 
2610         /**
2611          * set the score of the temporary candidate of current network selection procedure
2612          * @param score value set to mCandidateScore
2613          * @hide
2614          */
setCandidateScore(int score)2615         public void setCandidateScore(int score) {
2616             mCandidateScore = score;
2617         }
2618 
2619         /**
2620          * get the score of the temporary candidate of current network selection procedure
2621          * @return returns score of the temporary candidate of current network selection procedure
2622          * @hide
2623          */
getCandidateScore()2624         public int getCandidateScore() {
2625             return mCandidateScore;
2626         }
2627 
2628         /**
2629          * set the security type of the temporary candidate of current network selection procedure
2630          * @param params value to set to mCandidateSecurityParams
2631          * @hide
2632          */
setCandidateSecurityParams(SecurityParams params)2633         public void setCandidateSecurityParams(SecurityParams params) {
2634             mCandidateSecurityParams = params;
2635         }
2636 
2637         /**
2638          * get the security type of the temporary candidate of current network selection procedure
2639          * @return return the security params
2640          * @hide
2641          */
getCandidateSecurityParams()2642         public SecurityParams getCandidateSecurityParams() {
2643             return mCandidateSecurityParams;
2644         }
2645 
2646         /**
2647          * set the last used security type of the network
2648          * @param params value to set to mLastUsedSecurityParams
2649          * @hide
2650          */
setLastUsedSecurityParams(SecurityParams params)2651         public void setLastUsedSecurityParams(SecurityParams params) {
2652             mLastUsedSecurityParams = params;
2653         }
2654 
2655         /**
2656          * get the last used security type of the network
2657          * @return return the security params
2658          * @hide
2659          */
getLastUsedSecurityParams()2660         public SecurityParams getLastUsedSecurityParams() {
2661             return mLastUsedSecurityParams;
2662         }
2663 
2664         /**
2665          * get user preferred choice over this configuration
2666          * @return returns configKey of user preferred choice over this configuration
2667          * @hide
2668          */
getConnectChoice()2669         public String getConnectChoice() {
2670             return mConnectChoice;
2671         }
2672 
2673         /**
2674          * set user preferred choice over this configuration
2675          * @param newConnectChoice, the configKey of user preferred choice over this configuration
2676          * @hide
2677          */
setConnectChoice(String newConnectChoice)2678         public void setConnectChoice(String newConnectChoice) {
2679             mConnectChoice = newConnectChoice;
2680         }
2681 
2682         /**
2683          * Associate a RSSI with the user connect choice network.
2684          * @param rssi signal strength
2685          * @hide
2686          */
setConnectChoiceRssi(int rssi)2687         public void setConnectChoiceRssi(int rssi) {
2688             mConnectChoiceRssi = rssi;
2689         }
2690 
2691         /**
2692          * @return returns the RSSI of the last time the user made the connect choice.
2693          * @hide
2694          */
getConnectChoiceRssi()2695         public int getConnectChoiceRssi() {
2696             return mConnectChoiceRssi;
2697         }
2698 
2699         /** Get the current Quality network selection status as a String (for debugging). */
2700         @NonNull
getNetworkStatusString()2701         public String getNetworkStatusString() {
2702             return QUALITY_NETWORK_SELECTION_STATUS[mStatus];
2703         }
2704 
2705         /** @hide */
setHasEverConnected(boolean value)2706         public void setHasEverConnected(boolean value) {
2707             mHasEverConnected = value;
2708         }
2709 
2710         /** True if the device has ever connected to this network, false otherwise. */
hasEverConnected()2711         public boolean hasEverConnected() {
2712             return mHasEverConnected;
2713         }
2714 
2715         /**
2716          * Set whether a captive portal has never been detected on this network.
2717          * @hide
2718          */
setHasNeverDetectedCaptivePortal(boolean value)2719         public void setHasNeverDetectedCaptivePortal(boolean value) {
2720             mHasNeverDetectedCaptivePortal = value;
2721         }
2722 
2723         /** @hide */
hasNeverDetectedCaptivePortal()2724         public boolean hasNeverDetectedCaptivePortal() {
2725             return mHasNeverDetectedCaptivePortal;
2726         }
2727 
2728 
2729         /**
2730          * Get whether internet validation was ever successful on this WifiConfiguration.
2731          * @hide
2732          */
hasEverValidatedInternetAccess()2733         public boolean hasEverValidatedInternetAccess() {
2734             return mHasEverValidatedInternetAccess;
2735         }
2736 
2737         /**
2738          * @hide
2739          */
setHasEverValidatedInternetAccess(boolean everValidated)2740         public void setHasEverValidatedInternetAccess(boolean everValidated) {
2741             mHasEverValidatedInternetAccess = everValidated;
2742         }
2743 
2744         /** @hide */
NetworkSelectionStatus()2745         public NetworkSelectionStatus() {
2746             // previously stored configs will not have this parameter, so we default to false.
2747             mHasEverConnected = false;
2748         }
2749 
2750         /**
2751          * NetworkSelectionStatus exports an immutable public API.
2752          * However, test code has a need to construct a NetworkSelectionStatus in a specific state.
2753          * (Note that mocking using Mockito does not work if the object needs to be parceled and
2754          * unparceled.)
2755          * Export a @SystemApi Builder to allow tests to construct a NetworkSelectionStatus object
2756          * in the desired state, without sacrificing NetworkSelectionStatus's immutability.
2757          */
2758         @VisibleForTesting
2759         public static final class Builder {
2760             private final NetworkSelectionStatus mNetworkSelectionStatus =
2761                     new NetworkSelectionStatus();
2762 
2763             /**
2764              * Set the current network selection status.
2765              * One of:
2766              * {@link #NETWORK_SELECTION_ENABLED},
2767              * {@link #NETWORK_SELECTION_TEMPORARY_DISABLED},
2768              * {@link #NETWORK_SELECTION_PERMANENTLY_DISABLED}
2769              * @see NetworkSelectionStatus#getNetworkSelectionStatus()
2770              */
2771             @NonNull
setNetworkSelectionStatus(@etworkEnabledStatus int status)2772             public Builder setNetworkSelectionStatus(@NetworkEnabledStatus int status) {
2773                 mNetworkSelectionStatus.setNetworkSelectionStatus(status);
2774                 return this;
2775             }
2776 
2777             /**
2778              *
2779              * Set the current network's disable reason.
2780              * One of the {@link #DISABLED_NONE} or DISABLED_* constants.
2781              * e.g. {@link #DISABLED_ASSOCIATION_REJECTION}.
2782              * @see NetworkSelectionStatus#getNetworkSelectionDisableReason()
2783              */
2784             @NonNull
setNetworkSelectionDisableReason( @etworkSelectionDisableReason int reason)2785             public Builder setNetworkSelectionDisableReason(
2786                     @NetworkSelectionDisableReason int reason) {
2787                 mNetworkSelectionStatus.setNetworkSelectionDisableReason(reason);
2788                 return this;
2789             }
2790 
2791             /**
2792              * Build a NetworkSelectionStatus object.
2793              */
2794             @NonNull
build()2795             public NetworkSelectionStatus build() {
2796                 NetworkSelectionStatus status = new NetworkSelectionStatus();
2797                 status.copy(mNetworkSelectionStatus);
2798                 return status;
2799             }
2800         }
2801 
2802         /**
2803          * Get the network disable reason string for a reason code (for debugging).
2804          * @param reason specific error reason. One of the {@link #DISABLED_NONE} or
2805          *               DISABLED_* constants e.g. {@link #DISABLED_ASSOCIATION_REJECTION}.
2806          * @return network disable reason string, or null if the reason is invalid.
2807          */
2808         @Nullable
getNetworkSelectionDisableReasonString( @etworkSelectionDisableReason int reason)2809         public static String getNetworkSelectionDisableReasonString(
2810                 @NetworkSelectionDisableReason int reason) {
2811             DisableReasonInfo info = DISABLE_REASON_INFOS.get(reason);
2812             if (info == null) {
2813                 return null;
2814             } else {
2815                 return info.mReasonStr;
2816             }
2817         }
2818         /**
2819          * get current network disable reason
2820          * @return current network disable reason in String (for debug purpose)
2821          * @hide
2822          */
getNetworkSelectionDisableReasonString()2823         public String getNetworkSelectionDisableReasonString() {
2824             return getNetworkSelectionDisableReasonString(mNetworkSelectionDisableReason);
2825         }
2826 
2827         /**
2828          * Get the current network network selection status.
2829          * One of:
2830          * {@link #NETWORK_SELECTION_ENABLED},
2831          * {@link #NETWORK_SELECTION_TEMPORARY_DISABLED},
2832          * {@link #NETWORK_SELECTION_PERMANENTLY_DISABLED}
2833          */
2834         @NetworkEnabledStatus
getNetworkSelectionStatus()2835         public int getNetworkSelectionStatus() {
2836             return mStatus;
2837         }
2838 
2839         /**
2840          * True if the current network is enabled to join network selection, false otherwise.
2841          * @hide
2842          */
isNetworkEnabled()2843         public boolean isNetworkEnabled() {
2844             return mStatus == NETWORK_SELECTION_ENABLED;
2845         }
2846 
2847         /**
2848          * @return whether current network is temporary disabled
2849          * @hide
2850          */
isNetworkTemporaryDisabled()2851         public boolean isNetworkTemporaryDisabled() {
2852             return mStatus == NETWORK_SELECTION_TEMPORARY_DISABLED;
2853         }
2854 
2855         /**
2856          * True if the current network is permanently disabled, false otherwise.
2857          * @hide
2858          */
isNetworkPermanentlyDisabled()2859         public boolean isNetworkPermanentlyDisabled() {
2860             return mStatus == NETWORK_SELECTION_PERMANENTLY_DISABLED;
2861         }
2862 
2863         /**
2864          * set current network selection status
2865          * @param status network selection status to set
2866          * @hide
2867          */
setNetworkSelectionStatus(int status)2868         public void setNetworkSelectionStatus(int status) {
2869             if (status >= 0 && status < NETWORK_SELECTION_STATUS_MAX) {
2870                 mStatus = status;
2871             }
2872         }
2873 
2874         /**
2875          * Returns the current network's disable reason.
2876          * One of the {@link #DISABLED_NONE} or DISABLED_* constants
2877          * e.g. {@link #DISABLED_ASSOCIATION_REJECTION}.
2878          */
2879         @NetworkSelectionDisableReason
getNetworkSelectionDisableReason()2880         public int getNetworkSelectionDisableReason() {
2881             return mNetworkSelectionDisableReason;
2882         }
2883 
2884         /**
2885          * set Network disable reason
2886          * @param reason Network disable reason
2887          * @hide
2888          */
setNetworkSelectionDisableReason(@etworkSelectionDisableReason int reason)2889         public void setNetworkSelectionDisableReason(@NetworkSelectionDisableReason int reason) {
2890             if (reason >= 0 && reason < NETWORK_SELECTION_DISABLED_MAX) {
2891                 mNetworkSelectionDisableReason = reason;
2892             } else {
2893                 throw new IllegalArgumentException("Illegal reason value: " + reason);
2894             }
2895         }
2896 
2897         /**
2898          * @param timeStamp Set when current network is disabled in millisecond since boot.
2899          * @hide
2900          */
setDisableTime(long timeStamp)2901         public void setDisableTime(long timeStamp) {
2902             mTemporarilyDisabledTimestamp = timeStamp;
2903         }
2904 
2905         /**
2906          * Returns when the current network was disabled, in milliseconds since boot.
2907          */
getDisableTime()2908         public long getDisableTime() {
2909             return mTemporarilyDisabledTimestamp;
2910         }
2911 
2912         /**
2913          * Set the expected time for this WifiConfiguration to get re-enabled.
2914          * Timestamp is in milliseconds since boot.
2915          * @hide
2916          */
setDisableEndTime(long timestamp)2917         public void setDisableEndTime(long timestamp) {
2918             mTemporarilyDisabledEndTime = timestamp;
2919         }
2920 
2921         /**
2922          * Returns the expected time for this WifiConfiguration to get re-enabled.
2923          * Timestamp is in milliseconds since boot.
2924          * @hide
2925          */
getDisableEndTime()2926         public long getDisableEndTime() {
2927             return mTemporarilyDisabledEndTime;
2928         }
2929 
2930         /**
2931          * Get the disable counter of a specific reason.
2932          * @param reason specific failure reason. One of the {@link #DISABLED_NONE} or
2933          *              DISABLED_* constants e.g. {@link #DISABLED_ASSOCIATION_REJECTION}.
2934          * @exception IllegalArgumentException for invalid reason
2935          * @return counter number for specific error reason.
2936          */
getDisableReasonCounter(@etworkSelectionDisableReason int reason)2937         public int getDisableReasonCounter(@NetworkSelectionDisableReason int reason) {
2938             if (reason >= DISABLED_NONE && reason < NETWORK_SELECTION_DISABLED_MAX) {
2939                 return mNetworkSeclectionDisableCounter[reason];
2940             } else {
2941                 throw new IllegalArgumentException("Illegal reason value: " + reason);
2942             }
2943         }
2944 
2945         /**
2946          * set the counter of a specific failure reason
2947          * @param reason reason for disable error
2948          * @param value the counter value for this specific reason
2949          * @exception throw IllegalArgumentException for illegal input
2950          * @hide
2951          */
setDisableReasonCounter(int reason, int value)2952         public void setDisableReasonCounter(int reason, int value) {
2953             if (reason >= DISABLED_NONE && reason < NETWORK_SELECTION_DISABLED_MAX) {
2954                 mNetworkSeclectionDisableCounter[reason] = value;
2955             } else {
2956                 throw new IllegalArgumentException("Illegal reason value: " + reason);
2957             }
2958         }
2959 
2960         /**
2961          * increment the counter of a specific failure reason
2962          * @param reason a specific failure reason
2963          * @exception throw IllegalArgumentException for illegal input
2964          * @hide
2965          */
incrementDisableReasonCounter(int reason)2966         public void incrementDisableReasonCounter(int reason) {
2967             if (reason >= DISABLED_NONE && reason < NETWORK_SELECTION_DISABLED_MAX) {
2968                 mNetworkSeclectionDisableCounter[reason]++;
2969             } else {
2970                 throw new IllegalArgumentException("Illegal reason value: " + reason);
2971             }
2972         }
2973 
2974         /**
2975          * clear the counter of a specific failure reason
2976          * @param reason a specific failure reason
2977          * @exception throw IllegalArgumentException for illegal input
2978          * @hide
2979          */
clearDisableReasonCounter(int reason)2980         public void clearDisableReasonCounter(int reason) {
2981             if (reason >= DISABLED_NONE && reason < NETWORK_SELECTION_DISABLED_MAX) {
2982                 mNetworkSeclectionDisableCounter[reason] = DISABLED_NONE;
2983             } else {
2984                 throw new IllegalArgumentException("Illegal reason value: " + reason);
2985             }
2986         }
2987 
2988         /**
2989          * clear all the failure reason counters
2990          * @hide
2991          */
clearDisableReasonCounter()2992         public void clearDisableReasonCounter() {
2993             Arrays.fill(mNetworkSeclectionDisableCounter, DISABLED_NONE);
2994         }
2995 
2996         /**
2997          * BSSID for connection to this network (through network selection procedure)
2998          */
2999         private String mNetworkSelectionBSSID;
3000 
3001         /**
3002          * get current network Selection BSSID
3003          * @return current network Selection BSSID
3004          * @hide
3005          */
getNetworkSelectionBSSID()3006         public String getNetworkSelectionBSSID() {
3007             return mNetworkSelectionBSSID;
3008         }
3009 
3010         /**
3011          * set network Selection BSSID
3012          * @param bssid The target BSSID for assocaition
3013          * @hide
3014          */
setNetworkSelectionBSSID(String bssid)3015         public void setNetworkSelectionBSSID(String bssid) {
3016             mNetworkSelectionBSSID = bssid;
3017         }
3018 
3019         /** @hide */
copy(NetworkSelectionStatus source)3020         public void copy(NetworkSelectionStatus source) {
3021             mStatus = source.mStatus;
3022             mNetworkSelectionDisableReason = source.mNetworkSelectionDisableReason;
3023             mNetworkSeclectionDisableCounter = Arrays.copyOf(
3024                     source.mNetworkSeclectionDisableCounter,
3025                     source.mNetworkSeclectionDisableCounter.length);
3026             mTemporarilyDisabledTimestamp = source.mTemporarilyDisabledTimestamp;
3027             mTemporarilyDisabledEndTime = source.mTemporarilyDisabledEndTime;
3028             mNetworkSelectionBSSID = source.mNetworkSelectionBSSID;
3029             setSeenInLastQualifiedNetworkSelection(source.getSeenInLastQualifiedNetworkSelection());
3030             setCandidate(source.getCandidate());
3031             setCandidateScore(source.getCandidateScore());
3032             setCandidateSecurityParams(source.getCandidateSecurityParams());
3033             setLastUsedSecurityParams(source.getLastUsedSecurityParams());
3034             setConnectChoice(source.getConnectChoice());
3035             setConnectChoiceRssi(source.getConnectChoiceRssi());
3036             setHasEverConnected(source.hasEverConnected());
3037             setHasNeverDetectedCaptivePortal(source.hasNeverDetectedCaptivePortal());
3038             setHasEverValidatedInternetAccess(source.hasEverValidatedInternetAccess());
3039         }
3040 
3041         /** @hide */
writeToParcel(Parcel dest, int flags)3042         public void writeToParcel(Parcel dest, int flags) {
3043             dest.writeInt(getNetworkSelectionStatus());
3044             dest.writeInt(getNetworkSelectionDisableReason());
3045             for (int index = DISABLED_NONE; index < NETWORK_SELECTION_DISABLED_MAX;
3046                     index++) {
3047                 dest.writeInt(getDisableReasonCounter(index));
3048             }
3049             dest.writeLong(getDisableTime());
3050             dest.writeLong(getDisableEndTime());
3051             dest.writeString(getNetworkSelectionBSSID());
3052             if (getConnectChoice() != null) {
3053                 dest.writeInt(CONNECT_CHOICE_EXISTS);
3054                 dest.writeString(getConnectChoice());
3055                 dest.writeInt(getConnectChoiceRssi());
3056             } else {
3057                 dest.writeInt(CONNECT_CHOICE_NOT_EXISTS);
3058             }
3059             dest.writeInt(hasEverConnected() ? 1 : 0);
3060             dest.writeInt(hasNeverDetectedCaptivePortal() ? 1 : 0);
3061             dest.writeBoolean(hasEverValidatedInternetAccess());
3062             dest.writeParcelable(getCandidateSecurityParams(), flags);
3063             dest.writeParcelable(getLastUsedSecurityParams(), flags);
3064         }
3065 
3066         /** @hide */
readFromParcel(Parcel in)3067         public void readFromParcel(Parcel in) {
3068             setNetworkSelectionStatus(in.readInt());
3069             setNetworkSelectionDisableReason(in.readInt());
3070             for (int index = DISABLED_NONE; index < NETWORK_SELECTION_DISABLED_MAX;
3071                     index++) {
3072                 setDisableReasonCounter(index, in.readInt());
3073             }
3074             setDisableTime(in.readLong());
3075             setDisableEndTime(in.readLong());
3076             setNetworkSelectionBSSID(in.readString());
3077             if (in.readInt() == CONNECT_CHOICE_EXISTS) {
3078                 setConnectChoice(in.readString());
3079                 setConnectChoiceRssi(in.readInt());
3080             } else {
3081                 setConnectChoice(null);
3082             }
3083             setHasEverConnected(in.readInt() != 0);
3084             setHasNeverDetectedCaptivePortal(in.readInt() != 0);
3085             setHasEverValidatedInternetAccess(in.readBoolean());
3086             setCandidateSecurityParams((SecurityParams) in.readParcelable(null));
3087             setLastUsedSecurityParams((SecurityParams) in.readParcelable(null));
3088         }
3089     }
3090 
3091     /**
3092      * network selection related member
3093      * @hide
3094      */
3095     private NetworkSelectionStatus mNetworkSelectionStatus = new NetworkSelectionStatus();
3096 
3097     /**
3098      * This class is intended to store extra failure reason information for the most recent
3099      * connection attempt, so that it may be surfaced to the settings UI
3100      * @hide
3101      */
3102     // TODO(b/148626966): called by SUW via reflection, remove once SUW is updated
3103     public static class RecentFailure {
3104 
RecentFailure()3105         private RecentFailure() {}
3106 
3107         /**
3108          * Association Rejection Status code (NONE for success/non-association-rejection-fail)
3109          */
3110         @RecentFailureReason
3111         private int mAssociationStatus = RECENT_FAILURE_NONE;
3112         private long mLastUpdateTimeSinceBootMillis;
3113 
3114         /**
3115          * @param status the association status code for the recent failure
3116          */
setAssociationStatus(@ecentFailureReason int status, long updateTimeSinceBootMs)3117         public void setAssociationStatus(@RecentFailureReason int status,
3118                 long updateTimeSinceBootMs) {
3119             mAssociationStatus = status;
3120             mLastUpdateTimeSinceBootMillis = updateTimeSinceBootMs;
3121         }
3122         /**
3123          * Sets the RecentFailure to NONE
3124          */
clear()3125         public void clear() {
3126             mAssociationStatus = RECENT_FAILURE_NONE;
3127             mLastUpdateTimeSinceBootMillis = 0;
3128         }
3129         /**
3130          * Get the recent failure code. One of {@link #RECENT_FAILURE_NONE},
3131          * {@link #RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA},
3132          * {@link #RECENT_FAILURE_REFUSED_TEMPORARILY},
3133          * {@link #RECENT_FAILURE_POOR_CHANNEL_CONDITIONS}.
3134          * {@link #RECENT_FAILURE_DISCONNECTION_AP_BUSY}
3135          */
3136         @RecentFailureReason
getAssociationStatus()3137         public int getAssociationStatus() {
3138             return mAssociationStatus;
3139         }
3140 
3141         /**
3142          * Get the timestamp the failure status is last updated, in milliseconds since boot.
3143          */
getLastUpdateTimeSinceBootMillis()3144         public long getLastUpdateTimeSinceBootMillis() {
3145             return mLastUpdateTimeSinceBootMillis;
3146         }
3147     }
3148 
3149     /**
3150      * RecentFailure member
3151      * @hide
3152      */
3153     // TODO(b/148626966): called by SUW via reflection, once SUW is updated, make private and
3154     //  rename to mRecentFailure
3155     @NonNull
3156     public final RecentFailure recentFailure = new RecentFailure();
3157 
3158     /** @hide */
3159     @Retention(RetentionPolicy.SOURCE)
3160     @IntDef(prefix = "RECENT_FAILURE_", value = {
3161             RECENT_FAILURE_NONE,
3162             RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA,
3163             RECENT_FAILURE_REFUSED_TEMPORARILY,
3164             RECENT_FAILURE_POOR_CHANNEL_CONDITIONS,
3165             RECENT_FAILURE_DISCONNECTION_AP_BUSY,
3166             RECENT_FAILURE_MBO_ASSOC_DISALLOWED_UNSPECIFIED,
3167             RECENT_FAILURE_MBO_ASSOC_DISALLOWED_MAX_NUM_STA_ASSOCIATED,
3168             RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AIR_INTERFACE_OVERLOADED,
3169             RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AUTH_SERVER_OVERLOADED,
3170             RECENT_FAILURE_MBO_ASSOC_DISALLOWED_INSUFFICIENT_RSSI,
3171             RECENT_FAILURE_OCE_RSSI_BASED_ASSOCIATION_REJECTION,
3172             RECENT_FAILURE_NETWORK_NOT_FOUND
3173 
3174     })
3175     public @interface RecentFailureReason {}
3176 
3177     /**
3178      * No recent failure, or no specific reason given for the recent connection failure
3179      * @hide
3180      */
3181     @SystemApi
3182     public static final int RECENT_FAILURE_NONE = 0;
3183     /**
3184      * Connection to this network recently failed due to Association Rejection Status 17
3185      * (AP is full)
3186      * @hide
3187      */
3188     @SystemApi
3189     public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17;
3190 
3191     /**
3192      * Failed to connect because the association is rejected by the AP.
3193      * IEEE 802.11 association status code 30.
3194      * @hide
3195      */
3196     @SystemApi
3197     public static final int RECENT_FAILURE_REFUSED_TEMPORARILY = 1002;
3198 
3199     /**
3200      * Failed to connect because of excess frame loss and/or poor channel conditions.
3201      * IEEE 802.11 association status code 34.
3202      * @hide
3203      */
3204     @SystemApi
3205     public static final int RECENT_FAILURE_POOR_CHANNEL_CONDITIONS = 1003;
3206 
3207     /**
3208      * Disconnected by the AP because the AP can't handle all the associated stations.
3209      * IEEE 802.11 disconnection reason code 5.
3210      * @hide
3211      */
3212     @SystemApi
3213     public static final int RECENT_FAILURE_DISCONNECTION_AP_BUSY = 1004;
3214 
3215     /**
3216      * Failed to connect because the association is rejected by the AP with
3217      * MBO association disallowed Reason code: 1 - Unspecified or 0/6-255 - Reserved.
3218      * Details in MBO spec v1.2, 4.2.4 Table 13: MBO Association Disallowed attribute
3219      * @hide
3220      */
3221     @SystemApi
3222     public static final int RECENT_FAILURE_MBO_ASSOC_DISALLOWED_UNSPECIFIED = 1005;
3223 
3224     /**
3225      * Failed to connect because the association is rejected by the AP with
3226      * MBO association disallowed Reason code: 2 - Maximum number of associated stations reached.
3227      * Details in MBO spec v1.2, 4.2.4 Table 13: MBO Association Disallowed attribute
3228      * @hide
3229      */
3230     @SystemApi
3231     public static final int RECENT_FAILURE_MBO_ASSOC_DISALLOWED_MAX_NUM_STA_ASSOCIATED = 1006;
3232 
3233     /**
3234      * Failed to connect because the association is rejected by the AP with
3235      * MBO association disallowed Reason code: 3 - Air interface is overloaded.
3236      * Details in MBO spec v1.2, 4.2.4 Table 13: MBO Association Disallowed attribute
3237      * @hide
3238      */
3239     @SystemApi
3240     public static final int RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AIR_INTERFACE_OVERLOADED = 1007;
3241 
3242     /**
3243      * Failed to connect because the association is rejected by the AP with
3244      * MBO association disallowed Reason code: 4 - Authentication server overloaded.
3245      * Details in MBO spec v1.2, 4.2.4 Table 13: MBO Association Disallowed attribute
3246      * @hide
3247      */
3248     @SystemApi
3249     public static final int RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AUTH_SERVER_OVERLOADED = 1008;
3250 
3251     /**
3252      * Failed to connect because the association is rejected by the AP with
3253      * MBO association disallowed Reason code: 5 - Insufficient RSSI.
3254      * Details in MBO spec v1.2, 4.2.4 Table 13: MBO Association Disallowed attribute
3255      * @hide
3256      */
3257     @SystemApi
3258     public static final int RECENT_FAILURE_MBO_ASSOC_DISALLOWED_INSUFFICIENT_RSSI = 1009;
3259 
3260     /**
3261      * Failed to connect because the association is rejected by the AP with
3262      * OCE rssi based association rejection attribute.
3263      * Details in OCE spec v1.0, 3.14 Presence of OCE rssi based association rejection attribute.
3264      * @hide
3265      */
3266     @SystemApi
3267     public static final int RECENT_FAILURE_OCE_RSSI_BASED_ASSOCIATION_REJECTION = 1010;
3268 
3269     /**
3270      * Failed to connect because supplicant failed to find a network in scan result which
3271      * matches the network requested by framework for connection (including network capabilities).
3272      * @hide
3273      */
3274     @SystemApi
3275     public static final int RECENT_FAILURE_NETWORK_NOT_FOUND = 1011;
3276 
3277     /**
3278      * Get the failure reason for the most recent connection attempt, or
3279      * {@link #RECENT_FAILURE_NONE} if there was no failure.
3280      *
3281      * Failure reasons include:
3282      * {@link #RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA}
3283      * {@link #RECENT_FAILURE_REFUSED_TEMPORARILY}
3284      * {@link #RECENT_FAILURE_POOR_CHANNEL_CONDITIONS}
3285      * {@link #RECENT_FAILURE_DISCONNECTION_AP_BUSY}
3286      * {@link #RECENT_FAILURE_MBO_ASSOC_DISALLOWED_UNSPECIFIED}
3287      * {@link #RECENT_FAILURE_MBO_ASSOC_DISALLOWED_MAX_NUM_STA_ASSOCIATED}
3288      * {@link #RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AIR_INTERFACE_OVERLOADED}
3289      * {@link #RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AUTH_SERVER_OVERLOADED}
3290      * {@link #RECENT_FAILURE_MBO_ASSOC_DISALLOWED_INSUFFICIENT_RSSI}
3291      * {@link #RECENT_FAILURE_OCE_RSSI_BASED_ASSOCIATION_REJECTION}
3292      * {@link #RECENT_FAILURE_NETWORK_NOT_FOUND}
3293      * @hide
3294      */
3295     @RecentFailureReason
3296     @SystemApi
getRecentFailureReason()3297     public int getRecentFailureReason() {
3298         return recentFailure.getAssociationStatus();
3299     }
3300 
3301     /**
3302      * Get the network selection status.
3303      * @hide
3304      */
3305     @NonNull
3306     @SystemApi
getNetworkSelectionStatus()3307     public NetworkSelectionStatus getNetworkSelectionStatus() {
3308         return mNetworkSelectionStatus;
3309     }
3310 
3311     /**
3312      * Set the network selection status.
3313      * @hide
3314      */
3315     @SystemApi
setNetworkSelectionStatus(@onNull NetworkSelectionStatus status)3316     public void setNetworkSelectionStatus(@NonNull NetworkSelectionStatus status) {
3317         mNetworkSelectionStatus = status;
3318     }
3319 
3320     /**
3321      * Linked Configurations: represent the set of Wificonfigurations that are equivalent
3322      * regarding roaming and auto-joining.
3323      * The linked configuration may or may not have same SSID, and may or may not have same
3324      * credentials.
3325      * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server.
3326      * @hide
3327      */
3328     public HashMap<String, Integer>  linkedConfigurations;
3329 
3330     /** List of {@link OuiKeyedData} providing vendor-specific configuration data. */
3331     private @NonNull List<OuiKeyedData> mVendorData;
3332 
WifiConfiguration()3333     public WifiConfiguration() {
3334         networkId = INVALID_NETWORK_ID;
3335         SSID = null;
3336         BSSID = null;
3337         FQDN = null;
3338         roamingConsortiumIds = new long[0];
3339         priority = 0;
3340         mDeletionPriority = 0;
3341         hiddenSSID = false;
3342         allowedKeyManagement = new BitSet();
3343         allowedProtocols = new BitSet();
3344         allowedAuthAlgorithms = new BitSet();
3345         allowedPairwiseCiphers = new BitSet();
3346         allowedGroupCiphers = new BitSet();
3347         allowedGroupManagementCiphers = new BitSet();
3348         allowedSuiteBCiphers = new BitSet();
3349         wepKeys = new String[4];
3350         for (int i = 0; i < wepKeys.length; i++) {
3351             wepKeys[i] = null;
3352         }
3353         enterpriseConfig = new WifiEnterpriseConfig();
3354         ephemeral = false;
3355         osu = false;
3356         trusted = true; // Networks are considered trusted by default.
3357         oemPaid = false;
3358         oemPrivate = false;
3359         carrierMerged = false;
3360         fromWifiNetworkSuggestion = false;
3361         fromWifiNetworkSpecifier = false;
3362         meteredHint = false;
3363         mIsRepeaterEnabled = false;
3364         meteredOverride = METERED_OVERRIDE_NONE;
3365         useExternalScores = false;
3366         validatedInternetAccess = false;
3367         mIpConfiguration = new IpConfiguration();
3368         lastUpdateUid = -1;
3369         creatorUid = -1;
3370         shared = true;
3371         dtimInterval = 0;
3372         mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS);
3373         numRebootsSinceLastUse = 0;
3374         restricted = false;
3375         mBssidAllowlist = null;
3376         mIsDppConfigurator = false;
3377         mDppPrivateEcKey = new byte[0];
3378         mDppConnector = new byte[0];
3379         mDppCSignKey = new byte[0];
3380         mDppNetAccessKey = new byte[0];
3381         mHasPreSharedKeyChanged = false;
3382         mEncryptedPreSharedKey = new byte[0];
3383         mEncryptedPreSharedKeyIv = new byte[0];
3384         mIpProvisioningTimedOut = false;
3385         mVendorData = Collections.emptyList();
3386     }
3387 
3388     /**
3389      * Identify if this configuration represents a Passpoint network
3390      */
isPasspoint()3391     public boolean isPasspoint() {
3392         return !TextUtils.isEmpty(FQDN)
3393                 && !TextUtils.isEmpty(providerFriendlyName)
3394                 && enterpriseConfig != null
3395                 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE
3396                 && !TextUtils.isEmpty(mPasspointUniqueId);
3397     }
3398 
3399     /**
3400      * Helper function, identify if a configuration is linked
3401      * @hide
3402      */
isLinked(WifiConfiguration config)3403     public boolean isLinked(WifiConfiguration config) {
3404         if (config != null) {
3405             if (config.linkedConfigurations != null && linkedConfigurations != null) {
3406                 if (config.linkedConfigurations.get(getKey()) != null
3407                         && linkedConfigurations.get(config.getKey()) != null) {
3408                     return true;
3409                 }
3410             }
3411         }
3412         return  false;
3413     }
3414 
3415     /**
3416      * Helper function, idenfity if a configuration should be treated as an enterprise network
3417      * @hide
3418      */
3419     @UnsupportedAppUsage
isEnterprise()3420     public boolean isEnterprise() {
3421         if (enterpriseConfig == null
3422                 || enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.NONE) {
3423             return false;
3424         }
3425         for (SecurityParams p : mSecurityParamsList) {
3426             if (p.isEnterpriseSecurityType()) {
3427                 return true;
3428             }
3429         }
3430         return false;
3431     }
3432 
logTimeOfDay(long millis)3433     private static String logTimeOfDay(long millis) {
3434         Calendar c = Calendar.getInstance();
3435         if (millis >= 0) {
3436             LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(millis),
3437                     ZoneId.systemDefault());
3438             return localDateTime.toString();
3439         } else {
3440             return Long.toString(millis);
3441         }
3442     }
3443 
3444     @Override
toString()3445     public String toString() {
3446         StringBuilder sbuf = new StringBuilder();
3447         if (this.status == WifiConfiguration.Status.CURRENT) {
3448             sbuf.append("* ");
3449         } else if (this.status == WifiConfiguration.Status.DISABLED) {
3450             sbuf.append("- DSBLE ");
3451         }
3452         sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
3453                 append(" PROVIDER-NAME: ").append(this.providerFriendlyName).
3454                 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN)
3455                 .append(" HOME-PROVIDER-NETWORK: ").append(this.isHomeProviderNetwork)
3456                 .append(" PRIO: ").append(this.priority)
3457                 .append(" HIDDEN: ").append(this.hiddenSSID)
3458                 .append(" PMF: ").append(this.requirePmf)
3459                 .append(" CarrierId: ").append(this.carrierId)
3460                 .append(" SubscriptionId: ").append(this.subscriptionId)
3461                 .append(" SubscriptionGroup: ").append(this.mSubscriptionGroup)
3462                 .append(" Currently Connected: ").append(this.isCurrentlyConnected)
3463                 .append(" User Selected: ").append(this.mIsUserSelected)
3464                 .append('\n');
3465 
3466 
3467         sbuf.append(" NetworkSelectionStatus ")
3468                 .append(mNetworkSelectionStatus.getNetworkStatusString())
3469                 .append("\n");
3470         if (mNetworkSelectionStatus.getNetworkSelectionDisableReason() > 0) {
3471             sbuf.append(" mNetworkSelectionDisableReason ")
3472                     .append(mNetworkSelectionStatus.getNetworkSelectionDisableReasonString())
3473                     .append("\n");
3474 
3475             for (int index = NetworkSelectionStatus.DISABLED_NONE;
3476                     index < NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX; index++) {
3477                 if (mNetworkSelectionStatus.getDisableReasonCounter(index) != 0) {
3478                     sbuf.append(
3479                             NetworkSelectionStatus.getNetworkSelectionDisableReasonString(index))
3480                             .append(" counter:")
3481                             .append(mNetworkSelectionStatus.getDisableReasonCounter(index))
3482                             .append("\n");
3483                 }
3484             }
3485         }
3486         if (mNetworkSelectionStatus.getConnectChoice() != null) {
3487             sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice());
3488             sbuf.append(" connect choice rssi: ")
3489                     .append(mNetworkSelectionStatus.getConnectChoiceRssi());
3490         }
3491         sbuf.append(" hasEverConnected: ")
3492                 .append(mNetworkSelectionStatus.hasEverConnected()).append("\n");
3493         sbuf.append(" hasNeverDetectedCaptivePortal: ")
3494                 .append(mNetworkSelectionStatus.hasNeverDetectedCaptivePortal()).append("\n");
3495         sbuf.append(" hasEverValidatedInternetAccess: ")
3496                 .append(mNetworkSelectionStatus.hasEverValidatedInternetAccess()).append("\n");
3497         sbuf.append(" mCandidateSecurityParams: ")
3498                 .append(mNetworkSelectionStatus.getCandidateSecurityParams());
3499         sbuf.append(" mLastUsedSecurityParams: ")
3500                 .append(mNetworkSelectionStatus.getLastUsedSecurityParams());
3501 
3502         if (this.numAssociation > 0) {
3503             sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
3504         }
3505         if (this.numNoInternetAccessReports > 0) {
3506             sbuf.append(" numNoInternetAccessReports ");
3507             sbuf.append(this.numNoInternetAccessReports).append("\n");
3508         }
3509         if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess");
3510         if (this.shared) {
3511             sbuf.append(" shared");
3512         } else {
3513             sbuf.append(" not-shared");
3514         }
3515         if (this.ephemeral) sbuf.append(" ephemeral");
3516         if (this.osu) sbuf.append(" osu");
3517         if (this.trusted) sbuf.append(" trusted");
3518         if (this.restricted) sbuf.append(" restricted");
3519         if (this.oemPaid) sbuf.append(" oemPaid");
3520         if (this.oemPrivate) sbuf.append(" oemPrivate");
3521         if (this.carrierMerged) sbuf.append(" carrierMerged");
3522         if (this.fromWifiNetworkSuggestion) sbuf.append(" fromWifiNetworkSuggestion");
3523         if (this.fromWifiNetworkSpecifier) sbuf.append(" fromWifiNetworkSpecifier");
3524         if (this.meteredHint) sbuf.append(" meteredHint");
3525         if (this.mIsRepeaterEnabled) sbuf.append(" repeaterEnabled");
3526         if (this.useExternalScores) sbuf.append(" useExternalScores");
3527         if (this.validatedInternetAccess || this.ephemeral || this.trusted || this.oemPaid
3528                 || this.oemPrivate || this.carrierMerged || this.fromWifiNetworkSuggestion
3529                 || this.fromWifiNetworkSpecifier || this.meteredHint || this.useExternalScores
3530                 || this.restricted) {
3531             sbuf.append("\n");
3532         }
3533         if (this.meteredOverride != METERED_OVERRIDE_NONE) {
3534             sbuf.append(" meteredOverride ").append(meteredOverride).append("\n");
3535         }
3536         sbuf.append(" macRandomizationSetting: ").append(macRandomizationSetting).append("\n");
3537         sbuf.append(" mRandomizedMacAddress: ").append(mRandomizedMacAddress).append("\n");
3538         sbuf.append(" randomizedMacExpirationTimeMs: ")
3539                 .append(randomizedMacExpirationTimeMs == 0 ? "<none>"
3540                         : logTimeOfDay(randomizedMacExpirationTimeMs)).append("\n");
3541         sbuf.append(" randomizedMacLastModifiedTimeMs: ")
3542                 .append(randomizedMacLastModifiedTimeMs == 0 ? "<none>"
3543                         : logTimeOfDay(randomizedMacLastModifiedTimeMs)).append("\n");
3544         sbuf.append(" mIsSendDhcpHostnameEnabled: ").append(mIsSendDhcpHostnameEnabled)
3545                 .append("\n");
3546         sbuf.append(" deletionPriority: ").append(mDeletionPriority).append("\n");
3547         sbuf.append(" KeyMgmt:");
3548         for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
3549             if (this.allowedKeyManagement.get(k)) {
3550                 sbuf.append(" ");
3551                 if (k < KeyMgmt.strings.length) {
3552                     sbuf.append(KeyMgmt.strings[k]);
3553                 } else {
3554                     sbuf.append("??");
3555                 }
3556             }
3557         }
3558         sbuf.append(" Protocols:");
3559         for (int p = 0; p < this.allowedProtocols.size(); p++) {
3560             if (this.allowedProtocols.get(p)) {
3561                 sbuf.append(" ");
3562                 if (p < Protocol.strings.length) {
3563                     sbuf.append(Protocol.strings[p]);
3564                 } else {
3565                     sbuf.append("??");
3566                 }
3567             }
3568         }
3569         sbuf.append('\n');
3570         sbuf.append(" AuthAlgorithms:");
3571         for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) {
3572             if (this.allowedAuthAlgorithms.get(a)) {
3573                 sbuf.append(" ");
3574                 if (a < AuthAlgorithm.strings.length) {
3575                     sbuf.append(AuthAlgorithm.strings[a]);
3576                 } else {
3577                     sbuf.append("??");
3578                 }
3579             }
3580         }
3581         sbuf.append('\n');
3582         sbuf.append(" PairwiseCiphers:");
3583         for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) {
3584             if (this.allowedPairwiseCiphers.get(pc)) {
3585                 sbuf.append(" ");
3586                 if (pc < PairwiseCipher.strings.length) {
3587                     sbuf.append(PairwiseCipher.strings[pc]);
3588                 } else {
3589                     sbuf.append("??");
3590                 }
3591             }
3592         }
3593         sbuf.append('\n');
3594         sbuf.append(" GroupCiphers:");
3595         for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) {
3596             if (this.allowedGroupCiphers.get(gc)) {
3597                 sbuf.append(" ");
3598                 if (gc < GroupCipher.strings.length) {
3599                     sbuf.append(GroupCipher.strings[gc]);
3600                 } else {
3601                     sbuf.append("??");
3602                 }
3603             }
3604         }
3605         sbuf.append('\n');
3606         sbuf.append(" GroupMgmtCiphers:");
3607         for (int gmc = 0; gmc < this.allowedGroupManagementCiphers.size(); gmc++) {
3608             if (this.allowedGroupManagementCiphers.get(gmc)) {
3609                 sbuf.append(" ");
3610                 if (gmc < GroupMgmtCipher.strings.length) {
3611                     sbuf.append(GroupMgmtCipher.strings[gmc]);
3612                 } else {
3613                     sbuf.append("??");
3614                 }
3615             }
3616         }
3617         sbuf.append('\n');
3618         sbuf.append(" SuiteBCiphers:");
3619         for (int sbc = 0; sbc < this.allowedSuiteBCiphers.size(); sbc++) {
3620             if (this.allowedSuiteBCiphers.get(sbc)) {
3621                 sbuf.append(" ");
3622                 if (sbc < SuiteBCipher.strings.length) {
3623                     sbuf.append(SuiteBCipher.strings[sbc]);
3624                 } else {
3625                     sbuf.append("??");
3626                 }
3627             }
3628         }
3629         sbuf.append('\n').append(" PSK/SAE: ");
3630         if (this.preSharedKey != null) {
3631             sbuf.append('*');
3632         }
3633 
3634         sbuf.append("\nSecurityParams List:\n");
3635         mSecurityParamsList.forEach(params -> sbuf.append(params.toString()));
3636 
3637         sbuf.append("\nEnterprise config:\n");
3638         sbuf.append(enterpriseConfig);
3639 
3640         sbuf.append("IP config:\n");
3641         sbuf.append(mIpConfiguration.toString());
3642 
3643         if (mNetworkSelectionStatus.getNetworkSelectionBSSID() != null) {
3644             sbuf.append(" networkSelectionBSSID=").append(
3645                     mNetworkSelectionStatus.getNetworkSelectionBSSID());
3646         }
3647         long now_ms = SystemClock.elapsedRealtime();
3648         if (mNetworkSelectionStatus.getDisableTime() != NetworkSelectionStatus
3649                 .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP) {
3650             sbuf.append('\n');
3651             long diff = now_ms - mNetworkSelectionStatus.getDisableTime();
3652             if (diff <= 0) {
3653                 sbuf.append(" blackListed since <incorrect>");
3654             } else {
3655                 sbuf.append(" blackListed: ").append(Long.toString(diff / 1000)).append("sec ");
3656             }
3657         }
3658         if (mNetworkSelectionStatus.getDisableEndTime()
3659                 != NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP) {
3660             sbuf.append('\n');
3661             long diff = mNetworkSelectionStatus.getDisableEndTime() - now_ms;
3662             if (diff <= 0) {
3663                 sbuf.append(" blockListed remaining time <incorrect>");
3664             } else {
3665                 sbuf.append(" blocklist end in: ").append(Long.toString(diff / 1000))
3666                         .append("sec ");
3667             }
3668         }
3669         if (creatorUid != 0) sbuf.append(" cuid=").append(creatorUid);
3670         if (creatorName != null) sbuf.append(" cname=").append(creatorName);
3671         if (lastUpdateUid != 0) sbuf.append(" luid=").append(lastUpdateUid);
3672         if (lastUpdateName != null) sbuf.append(" lname=").append(lastUpdateName);
3673         if (updateIdentifier != null) sbuf.append(" updateIdentifier=").append(updateIdentifier);
3674         sbuf.append(" lcuid=").append(lastConnectUid);
3675         sbuf.append(" allowAutojoin=").append(allowAutojoin);
3676         sbuf.append(" noInternetAccessExpected=").append(noInternetAccessExpected);
3677         sbuf.append(" mostRecentlyConnected=").append(isMostRecentlyConnected);
3678 
3679         sbuf.append(" ");
3680 
3681         if (this.lastConnected != 0) {
3682             sbuf.append('\n');
3683             sbuf.append("lastConnected: ").append(logTimeOfDay(this.lastConnected));
3684             sbuf.append(" ");
3685         }
3686         sbuf.append('\n');
3687         if (this.lastUpdated != 0) {
3688             sbuf.append('\n');
3689             sbuf.append("lastUpdated: ").append(logTimeOfDay(this.lastUpdated));
3690             sbuf.append(" ");
3691         }
3692         sbuf.append('\n');
3693         sbuf.append("numRebootsSinceLastUse: ").append(numRebootsSinceLastUse).append('\n');
3694         if (this.linkedConfigurations != null) {
3695             for (String key : this.linkedConfigurations.keySet()) {
3696                 sbuf.append(" linked: ").append(key);
3697                 sbuf.append('\n');
3698             }
3699         }
3700         sbuf.append("recentFailure: ").append("Association Rejection code: ")
3701                 .append(recentFailure.getAssociationStatus()).append(", last update time: ")
3702                 .append(recentFailure.getLastUpdateTimeSinceBootMillis()).append("\n");
3703         if (mBssidAllowlist != null) {
3704             sbuf.append("bssidAllowList: [");
3705             for (MacAddress bssid : mBssidAllowlist) {
3706                 sbuf.append(bssid).append(", ");
3707             }
3708             sbuf.append("]");
3709         } else {
3710             sbuf.append("bssidAllowlist unset");
3711         }
3712         sbuf.append("\n");
3713         if (mVendorData != null && !mVendorData.isEmpty()) {
3714             sbuf.append("vendorData: ").append(mVendorData);
3715         } else {
3716             sbuf.append("vendorData unset");
3717         }
3718         sbuf.append("\n");
3719         sbuf.append("IsDppConfigurator: ").append(this.mIsDppConfigurator).append("\n");
3720         sbuf.append("HasEncryptedPreSharedKey: ").append(hasEncryptedPreSharedKey()).append("\n");
3721         sbuf.append(" setWifi7Enabled=").append(mWifi7Enabled);
3722         return sbuf.toString();
3723     }
3724 
3725     /**
3726      * Get the SSID in a human-readable format, with all additional formatting removed
3727      * e.g. quotation marks around the SSID, "P" prefix
3728      * @hide
3729      */
3730     @NonNull
3731     @SystemApi
getPrintableSsid()3732     public String getPrintableSsid() {
3733         // TODO(b/136480579): Handle SSIDs with non-UTF-8 encodings.
3734         return WifiInfo.removeDoubleQuotes(SSID);
3735     }
3736 
3737     /**
3738      * Get an identifier for associating credentials with this config
3739      * @param current configuration contains values for additional fields
3740      *                that are not part of this configuration. Used
3741      *                when a config with some fields is passed by an application.
3742      * @throws IllegalStateException if config is invalid for key id generation
3743      * @hide
3744      */
getKeyIdForCredentials(WifiConfiguration current)3745     public String getKeyIdForCredentials(WifiConfiguration current) {
3746         String keyMgmt = "";
3747 
3748         try {
3749             // Get current config details for fields that are not initialized
3750             if (TextUtils.isEmpty(SSID)) SSID = current.SSID;
3751             if (allowedKeyManagement.cardinality() == 0) {
3752                 allowedKeyManagement = current.allowedKeyManagement;
3753             }
3754             if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
3755                 keyMgmt += KeyMgmt.strings[KeyMgmt.WPA_EAP];
3756             }
3757             if (allowedKeyManagement.get(KeyMgmt.OSEN)) {
3758                 keyMgmt += KeyMgmt.strings[KeyMgmt.OSEN];
3759             }
3760             if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
3761                 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X];
3762             }
3763             if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
3764                 keyMgmt += KeyMgmt.strings[KeyMgmt.SUITE_B_192];
3765             }
3766             if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {
3767                 keyMgmt += KeyMgmt.strings[KeyMgmt.WAPI_CERT];
3768             }
3769 
3770             if (TextUtils.isEmpty(keyMgmt)) {
3771                 throw new IllegalStateException("Not an EAP network");
3772             }
3773             String keyId = (!TextUtils.isEmpty(SSID) && SSID.charAt(0) != '\"'
3774                     ? SSID.toLowerCase() : SSID) + "_" + keyMgmt + "_"
3775                     + trimStringForKeyId(enterpriseConfig.getKeyId(current != null
3776                     ? current.enterpriseConfig : null));
3777 
3778             if (!fromWifiNetworkSuggestion) {
3779                 return keyId;
3780             }
3781             return keyId + "_" + trimStringForKeyId(BSSID) + "_" + trimStringForKeyId(creatorName);
3782         } catch (NullPointerException e) {
3783             throw new IllegalStateException("Invalid config details");
3784         }
3785     }
3786 
trimStringForKeyId(String string)3787     private String trimStringForKeyId(String string) {
3788         if (string == null) {
3789             return "";
3790         }
3791         // Remove quotes and spaces
3792         return string.replace("\"", "").replace(" ", "");
3793     }
3794 
readBitSet(Parcel src)3795     private static BitSet readBitSet(Parcel src) {
3796         int cardinality = src.readInt();
3797 
3798         BitSet set = new BitSet();
3799         for (int i = 0; i < cardinality; i++) {
3800             set.set(src.readInt());
3801         }
3802 
3803         return set;
3804     }
3805 
writeBitSet(Parcel dest, BitSet set)3806     private static void writeBitSet(Parcel dest, BitSet set) {
3807         int nextSetBit = -1;
3808 
3809         dest.writeInt(set.cardinality());
3810 
3811         while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
3812             dest.writeInt(nextSetBit);
3813         }
3814     }
3815 
3816     /**
3817      * Get the authentication type of the network.
3818      * @return One of the {@link KeyMgmt} constants. e.g. {@link KeyMgmt#WPA2_PSK}.
3819      * @throws IllegalStateException if config is invalid for authentication type.
3820      * @hide
3821      */
3822     @SystemApi
3823     @KeyMgmt.KeyMgmtScheme
getAuthType()3824     public int getAuthType() {
3825         if (allowedKeyManagement.cardinality() > 1) {
3826             if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
3827                 if (allowedKeyManagement.cardinality() == 2
3828                         && allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
3829                     return KeyMgmt.WPA_EAP;
3830                 }
3831                 if (allowedKeyManagement.cardinality() == 3
3832                         && allowedKeyManagement.get(KeyMgmt.IEEE8021X)
3833                         && allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
3834                     return KeyMgmt.SUITE_B_192;
3835                 }
3836             }
3837             throw new IllegalStateException("Invalid auth type set: " + allowedKeyManagement);
3838         }
3839         if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
3840             return KeyMgmt.WPA_PSK;
3841         } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
3842             return KeyMgmt.WPA2_PSK;
3843         } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
3844             return KeyMgmt.WPA_EAP;
3845         } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
3846             return KeyMgmt.IEEE8021X;
3847         } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
3848             return KeyMgmt.SAE;
3849         } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
3850             return KeyMgmt.OWE;
3851         } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
3852             return KeyMgmt.SUITE_B_192;
3853         } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) {
3854             return KeyMgmt.WAPI_PSK;
3855         } else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {
3856             return KeyMgmt.WAPI_CERT;
3857         } else if (allowedKeyManagement.get(KeyMgmt.DPP)) {
3858             return KeyMgmt.DPP;
3859         }
3860         return KeyMgmt.NONE;
3861     }
3862 
3863     /**
3864      * Return a String that can be used to uniquely identify this WifiConfiguration.
3865      * <br />
3866      * Note: Do not persist this value! This value is not guaranteed to remain backwards compatible.
3867      */
3868     @NonNull
getKey()3869     public String getKey() {
3870         // Passpoint ephemeral networks have their unique identifier set. Return it as is to be
3871         // able to match internally.
3872         if (mPasspointUniqueId != null) {
3873             return mPasspointUniqueId;
3874         }
3875 
3876         String key = getSsidAndSecurityTypeString();
3877         if (!shared) {
3878             key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier();
3879         }
3880 
3881         return key;
3882     }
3883 
3884     /**
3885      * Get a unique key which represent this Wi-Fi network. If two profiles are for
3886      * the same Wi-Fi network, but from different provider, they would have the same key.
3887      * @hide
3888      */
getNetworkKey()3889     public String getNetworkKey() {
3890         // Passpoint ephemeral networks have their unique identifier set. Return it as is to be
3891         // able to match internally.
3892         if (mPasspointUniqueId != null) {
3893             return mPasspointUniqueId;
3894         }
3895 
3896         String key = getSsidAndSecurityTypeString();
3897         if (!shared) {
3898             key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier();
3899         }
3900 
3901         return key;
3902     }
3903 
3904     /** @hide
3905      *  return the SSID + security type in String format.
3906      */
getSsidAndSecurityTypeString()3907     public String getSsidAndSecurityTypeString() {
3908         return (!TextUtils.isEmpty(SSID) && SSID.charAt(0) != '\"' ? SSID.toLowerCase() : SSID)
3909                 + getDefaultSecurityType();
3910     }
3911 
3912     /**
3913      * Get the IpConfiguration object associated with this WifiConfiguration.
3914      * @hide
3915      */
3916     @NonNull
3917     @SystemApi
getIpConfiguration()3918     public IpConfiguration getIpConfiguration() {
3919         return new IpConfiguration(mIpConfiguration);
3920     }
3921 
3922     /**
3923      * Set the {@link IpConfiguration} for this network.
3924      *
3925      * @param ipConfiguration a {@link IpConfiguration} to use for this Wi-Fi configuration, or
3926      *                        {@code null} to use the default configuration.
3927      */
setIpConfiguration(@ullable IpConfiguration ipConfiguration)3928     public void setIpConfiguration(@Nullable IpConfiguration ipConfiguration) {
3929         if (ipConfiguration == null) ipConfiguration = new IpConfiguration();
3930         mIpConfiguration = ipConfiguration;
3931     }
3932 
3933     /**
3934      * Get the {@link StaticIpConfiguration} for this network.
3935      * @return the {@link StaticIpConfiguration}, or null if unset.
3936      * @hide
3937      */
3938     @Nullable
3939     @UnsupportedAppUsage
getStaticIpConfiguration()3940     public StaticIpConfiguration getStaticIpConfiguration() {
3941         return mIpConfiguration.getStaticIpConfiguration();
3942     }
3943 
3944     /** @hide */
3945     @UnsupportedAppUsage
setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration)3946     public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
3947         mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration);
3948     }
3949 
3950     /**
3951      * Get the {@link IpConfiguration.IpAssignment} for this network.
3952      * @hide
3953      */
3954     @NonNull
3955     @UnsupportedAppUsage
getIpAssignment()3956     public IpConfiguration.IpAssignment getIpAssignment() {
3957         return mIpConfiguration.getIpAssignment();
3958     }
3959 
3960     /** @hide */
3961     @UnsupportedAppUsage
setIpAssignment(IpConfiguration.IpAssignment ipAssignment)3962     public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) {
3963         mIpConfiguration.setIpAssignment(ipAssignment);
3964     }
3965 
3966     /**
3967      * Get the {@link IpConfiguration.ProxySettings} for this network.
3968      * @hide
3969      */
3970     @NonNull
3971     @UnsupportedAppUsage
getProxySettings()3972     public IpConfiguration.ProxySettings getProxySettings() {
3973         return mIpConfiguration.getProxySettings();
3974     }
3975 
3976     /** @hide */
3977     @UnsupportedAppUsage
setProxySettings(IpConfiguration.ProxySettings proxySettings)3978     public void setProxySettings(IpConfiguration.ProxySettings proxySettings) {
3979         mIpConfiguration.setProxySettings(proxySettings);
3980     }
3981 
3982     /**
3983      * Returns the HTTP proxy used by this object.
3984      * @return a {@link ProxyInfo httpProxy} representing the proxy specified by this
3985      *                  WifiConfiguration, or {@code null} if no proxy is specified.
3986      */
getHttpProxy()3987     public ProxyInfo getHttpProxy() {
3988         if (mIpConfiguration.getProxySettings() == IpConfiguration.ProxySettings.NONE) {
3989             return null;
3990         }
3991         return new ProxyInfo(mIpConfiguration.getHttpProxy());
3992     }
3993 
3994     /**
3995      * Set the {@link ProxyInfo} for this WifiConfiguration. This method should only be used by a
3996      * device owner or profile owner. When other apps attempt to save a {@link WifiConfiguration}
3997      * with modified proxy settings, the methods {@link WifiManager#addNetwork} and
3998      * {@link WifiManager#updateNetwork} fail and return {@code -1}.
3999      *
4000      * @param httpProxy {@link ProxyInfo} representing the httpProxy to be used by this
4001      *                  WifiConfiguration. Setting this to {@code null} will explicitly set no
4002      *                  proxy, removing any proxy that was previously set.
4003      */
setHttpProxy(ProxyInfo httpProxy)4004     public void setHttpProxy(ProxyInfo httpProxy) {
4005         if (httpProxy == null) {
4006             mIpConfiguration.setProxySettings(IpConfiguration.ProxySettings.NONE);
4007             mIpConfiguration.setHttpProxy(null);
4008             return;
4009         }
4010         ProxyInfo httpProxyCopy;
4011         ProxySettings proxySettingCopy;
4012         if (!Uri.EMPTY.equals(httpProxy.getPacFileUrl())) {
4013             proxySettingCopy = IpConfiguration.ProxySettings.PAC;
4014             // Construct a new PAC URL Proxy
4015             httpProxyCopy = ProxyInfo.buildPacProxy(httpProxy.getPacFileUrl(), httpProxy.getPort());
4016         } else {
4017             proxySettingCopy = IpConfiguration.ProxySettings.STATIC;
4018             // Construct a new HTTP Proxy
4019             String[] exclusionList = httpProxy.getExclusionList();
4020             if (exclusionList == null) {
4021                 exclusionList = new String[0];
4022             }
4023             httpProxyCopy = ProxyInfo.buildDirectProxy(httpProxy.getHost(), httpProxy.getPort(),
4024                     Arrays.asList(exclusionList));
4025         }
4026         if (!httpProxyCopy.isValid()) {
4027             Log.w(TAG, "ProxyInfo is not valid: " + httpProxyCopy);
4028         }
4029         mIpConfiguration.setProxySettings(proxySettingCopy);
4030         mIpConfiguration.setHttpProxy(httpProxyCopy);
4031     }
4032 
4033     /**
4034      * Set the {@link ProxySettings} and {@link ProxyInfo} for this network.
4035      * @hide
4036      */
4037     @UnsupportedAppUsage
setProxy(@onNull ProxySettings settings, @NonNull ProxyInfo proxy)4038     public void setProxy(@NonNull ProxySettings settings, @NonNull ProxyInfo proxy) {
4039         mIpConfiguration.setProxySettings(settings);
4040         mIpConfiguration.setHttpProxy(proxy);
4041     }
4042 
4043     /** Implement the Parcelable interface {@hide} */
describeContents()4044     public int describeContents() {
4045         return 0;
4046     }
4047 
4048     /** @hide */
setPasspointManagementObjectTree(String passpointManagementObjectTree)4049     public void setPasspointManagementObjectTree(String passpointManagementObjectTree) {
4050         mPasspointManagementObjectTree = passpointManagementObjectTree;
4051     }
4052 
4053     /** @hide */
getMoTree()4054     public String getMoTree() {
4055         return mPasspointManagementObjectTree;
4056     }
4057 
4058     /** Copy constructor */
WifiConfiguration(@onNull WifiConfiguration source)4059     public WifiConfiguration(@NonNull WifiConfiguration source) {
4060         if (source != null) {
4061             networkId = source.networkId;
4062             status = source.status;
4063             SSID = source.SSID;
4064             BSSID = source.BSSID;
4065             FQDN = source.FQDN;
4066             roamingConsortiumIds = source.roamingConsortiumIds.clone();
4067             providerFriendlyName = source.providerFriendlyName;
4068             isHomeProviderNetwork = source.isHomeProviderNetwork;
4069             preSharedKey = source.preSharedKey;
4070 
4071             mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus());
4072             apBand = source.apBand;
4073             apChannel = source.apChannel;
4074 
4075             wepKeys = new String[4];
4076             for (int i = 0; i < wepKeys.length; i++) {
4077                 wepKeys[i] = source.wepKeys[i];
4078             }
4079 
4080             wepTxKeyIndex = source.wepTxKeyIndex;
4081             priority = source.priority;
4082             mDeletionPriority = source.mDeletionPriority;
4083             hiddenSSID = source.hiddenSSID;
4084             allowedKeyManagement   = (BitSet) source.allowedKeyManagement.clone();
4085             allowedProtocols       = (BitSet) source.allowedProtocols.clone();
4086             allowedAuthAlgorithms  = (BitSet) source.allowedAuthAlgorithms.clone();
4087             allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone();
4088             allowedGroupCiphers    = (BitSet) source.allowedGroupCiphers.clone();
4089             allowedGroupManagementCiphers = (BitSet) source.allowedGroupManagementCiphers.clone();
4090             allowedSuiteBCiphers    = (BitSet) source.allowedSuiteBCiphers.clone();
4091             mSecurityParamsList = new ArrayList<>(source.mSecurityParamsList.size());
4092             source.mSecurityParamsList.forEach(p -> mSecurityParamsList.add(new SecurityParams(p)));
4093             enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
4094 
4095             defaultGwMacAddress = source.defaultGwMacAddress;
4096 
4097             mIpConfiguration = new IpConfiguration(source.mIpConfiguration);
4098 
4099             if ((source.linkedConfigurations != null)
4100                     && (source.linkedConfigurations.size() > 0)) {
4101                 linkedConfigurations = new HashMap<String, Integer>();
4102                 linkedConfigurations.putAll(source.linkedConfigurations);
4103             }
4104             validatedInternetAccess = source.validatedInternetAccess;
4105             isLegacyPasspointConfig = source.isLegacyPasspointConfig;
4106             ephemeral = source.ephemeral;
4107             osu = source.osu;
4108             trusted = source.trusted;
4109             restricted = source.restricted;
4110             oemPaid = source.oemPaid;
4111             oemPrivate = source.oemPrivate;
4112             carrierMerged = source.carrierMerged;
4113             fromWifiNetworkSuggestion = source.fromWifiNetworkSuggestion;
4114             fromWifiNetworkSpecifier = source.fromWifiNetworkSpecifier;
4115             meteredHint = source.meteredHint;
4116             mIsRepeaterEnabled = source.mIsRepeaterEnabled;
4117             meteredOverride = source.meteredOverride;
4118             useExternalScores = source.useExternalScores;
4119 
4120             lastConnectUid = source.lastConnectUid;
4121             lastUpdateUid = source.lastUpdateUid;
4122             creatorUid = source.creatorUid;
4123             creatorName = source.creatorName;
4124             lastUpdateName = source.lastUpdateName;
4125             peerWifiConfiguration = source.peerWifiConfiguration;
4126 
4127             lastConnected = source.lastConnected;
4128             lastDisconnected = source.lastDisconnected;
4129             lastUpdated = source.lastUpdated;
4130             numRebootsSinceLastUse = source.numRebootsSinceLastUse;
4131             numScorerOverride = source.numScorerOverride;
4132             numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
4133             numAssociation = source.numAssociation;
4134             allowAutojoin = source.allowAutojoin;
4135             numNoInternetAccessReports = source.numNoInternetAccessReports;
4136             noInternetAccessExpected = source.noInternetAccessExpected;
4137             shared = source.shared;
4138             recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus(),
4139                     source.recentFailure.getLastUpdateTimeSinceBootMillis());
4140             mRandomizedMacAddress = source.mRandomizedMacAddress;
4141             macRandomizationSetting = source.macRandomizationSetting;
4142             randomizedMacExpirationTimeMs = source.randomizedMacExpirationTimeMs;
4143             randomizedMacLastModifiedTimeMs = source.randomizedMacLastModifiedTimeMs;
4144             mIsSendDhcpHostnameEnabled = source.mIsSendDhcpHostnameEnabled;
4145             requirePmf = source.requirePmf;
4146             updateIdentifier = source.updateIdentifier;
4147             carrierId = source.carrierId;
4148             subscriptionId = source.subscriptionId;
4149             mPasspointUniqueId = source.mPasspointUniqueId;
4150             mSubscriptionGroup = source.mSubscriptionGroup;
4151             if (source.mBssidAllowlist != null) {
4152                 mBssidAllowlist = new ArrayList<>(source.mBssidAllowlist);
4153             } else {
4154                 mBssidAllowlist = null;
4155             }
4156             mIsDppConfigurator = source.mIsDppConfigurator;
4157             mDppPrivateEcKey = source.mDppPrivateEcKey.clone();
4158             mDppConnector = source.mDppConnector.clone();
4159             mDppCSignKey = source.mDppCSignKey.clone();
4160             mDppNetAccessKey = source.mDppNetAccessKey.clone();
4161             isCurrentlyConnected = source.isCurrentlyConnected;
4162             mIsUserSelected = source.mIsUserSelected;
4163             mHasPreSharedKeyChanged = source.hasPreSharedKeyChanged();
4164             mEncryptedPreSharedKey = source.mEncryptedPreSharedKey != null
4165                     ? source.mEncryptedPreSharedKey.clone() : new byte[0];
4166             mEncryptedPreSharedKeyIv = source.mEncryptedPreSharedKeyIv != null
4167                     ? source.mEncryptedPreSharedKeyIv.clone() : new byte[0];
4168             mIpProvisioningTimedOut = source.mIpProvisioningTimedOut;
4169             mVendorData = new ArrayList<>(source.mVendorData);
4170             mWifi7Enabled = source.mWifi7Enabled;
4171         }
4172     }
4173 
4174     /** Implement the Parcelable interface {@hide} */
4175     @Override
writeToParcel(Parcel dest, int flags)4176     public void writeToParcel(Parcel dest, int flags) {
4177         dest.writeInt(networkId);
4178         dest.writeInt(status);
4179         mNetworkSelectionStatus.writeToParcel(dest, flags);
4180         dest.writeString(SSID);
4181         dest.writeString(BSSID);
4182         dest.writeInt(apBand);
4183         dest.writeInt(apChannel);
4184         dest.writeString(FQDN);
4185         dest.writeString(providerFriendlyName);
4186         dest.writeInt(isHomeProviderNetwork ? 1 : 0);
4187         dest.writeInt(roamingConsortiumIds.length);
4188         for (long roamingConsortiumId : roamingConsortiumIds) {
4189             dest.writeLong(roamingConsortiumId);
4190         }
4191         dest.writeString(preSharedKey);
4192         for (String wepKey : wepKeys) {
4193             dest.writeString(wepKey);
4194         }
4195         dest.writeInt(wepTxKeyIndex);
4196         dest.writeInt(priority);
4197         dest.writeInt(mDeletionPriority);
4198         dest.writeInt(hiddenSSID ? 1 : 0);
4199         dest.writeInt(requirePmf ? 1 : 0);
4200         dest.writeString(updateIdentifier);
4201 
4202         writeBitSet(dest, allowedKeyManagement);
4203         writeBitSet(dest, allowedProtocols);
4204         writeBitSet(dest, allowedAuthAlgorithms);
4205         writeBitSet(dest, allowedPairwiseCiphers);
4206         writeBitSet(dest, allowedGroupCiphers);
4207         writeBitSet(dest, allowedGroupManagementCiphers);
4208         writeBitSet(dest, allowedSuiteBCiphers);
4209 
4210         dest.writeInt(mSecurityParamsList.size());
4211         mSecurityParamsList.forEach(params -> dest.writeParcelable(params, flags));
4212 
4213         dest.writeParcelable(enterpriseConfig, flags);
4214 
4215         dest.writeParcelable(mIpConfiguration, flags);
4216         dest.writeString(dhcpServer);
4217         dest.writeString(defaultGwMacAddress);
4218         dest.writeInt(validatedInternetAccess ? 1 : 0);
4219         dest.writeInt(isLegacyPasspointConfig ? 1 : 0);
4220         dest.writeInt(ephemeral ? 1 : 0);
4221         dest.writeInt(trusted ? 1 : 0);
4222         dest.writeInt(oemPaid ? 1 : 0);
4223         dest.writeInt(oemPrivate ? 1 : 0);
4224         dest.writeInt(carrierMerged ? 1 : 0);
4225         dest.writeInt(fromWifiNetworkSuggestion ? 1 : 0);
4226         dest.writeInt(fromWifiNetworkSpecifier ? 1 : 0);
4227         dest.writeInt(meteredHint ? 1 : 0);
4228         dest.writeBoolean(mIsRepeaterEnabled);
4229         dest.writeInt(meteredOverride);
4230         dest.writeInt(useExternalScores ? 1 : 0);
4231         dest.writeInt(creatorUid);
4232         dest.writeInt(lastConnectUid);
4233         dest.writeInt(lastUpdateUid);
4234         dest.writeString(creatorName);
4235         dest.writeString(lastUpdateName);
4236         dest.writeInt(numScorerOverride);
4237         dest.writeInt(numScorerOverrideAndSwitchedNetwork);
4238         dest.writeInt(numAssociation);
4239         dest.writeBoolean(allowAutojoin);
4240         dest.writeInt(numNoInternetAccessReports);
4241         dest.writeInt(noInternetAccessExpected ? 1 : 0);
4242         dest.writeInt(shared ? 1 : 0);
4243         dest.writeString(mPasspointManagementObjectTree);
4244         dest.writeInt(recentFailure.getAssociationStatus());
4245         dest.writeLong(recentFailure.getLastUpdateTimeSinceBootMillis());
4246         dest.writeParcelable(mRandomizedMacAddress, flags);
4247         dest.writeInt(macRandomizationSetting);
4248         dest.writeBoolean(mIsSendDhcpHostnameEnabled);
4249         dest.writeInt(osu ? 1 : 0);
4250         dest.writeLong(randomizedMacExpirationTimeMs);
4251         dest.writeLong(randomizedMacLastModifiedTimeMs);
4252         dest.writeInt(carrierId);
4253         dest.writeString(mPasspointUniqueId);
4254         dest.writeInt(subscriptionId);
4255         dest.writeBoolean(restricted);
4256         dest.writeParcelable(mSubscriptionGroup, flags);
4257         dest.writeList(mBssidAllowlist);
4258         dest.writeBoolean(mIsDppConfigurator);
4259         dest.writeByteArray(mDppPrivateEcKey);
4260         dest.writeByteArray(mDppConnector);
4261         dest.writeByteArray(mDppCSignKey);
4262         dest.writeByteArray(mDppNetAccessKey);
4263         dest.writeBoolean(isCurrentlyConnected);
4264         dest.writeBoolean(mIsUserSelected);
4265         dest.writeBoolean(mHasPreSharedKeyChanged);
4266         dest.writeByteArray(mEncryptedPreSharedKey);
4267         dest.writeByteArray(mEncryptedPreSharedKeyIv);
4268         dest.writeBoolean(mIpProvisioningTimedOut);
4269         dest.writeList(mVendorData);
4270         dest.writeBoolean(mWifi7Enabled);
4271     }
4272 
4273     /** Implement the Parcelable interface {@hide} */
4274     @SystemApi
4275     public static final @android.annotation.NonNull Creator<WifiConfiguration> CREATOR =
4276             new Creator<WifiConfiguration>() {
4277                 public WifiConfiguration createFromParcel(Parcel in) {
4278                     WifiConfiguration config = new WifiConfiguration();
4279                     config.networkId = in.readInt();
4280                     config.status = in.readInt();
4281                     config.mNetworkSelectionStatus.readFromParcel(in);
4282                     config.SSID = in.readString();
4283                     config.BSSID = in.readString();
4284                     config.apBand = in.readInt();
4285                     config.apChannel = in.readInt();
4286                     config.FQDN = in.readString();
4287                     config.providerFriendlyName = in.readString();
4288                     config.isHomeProviderNetwork = in.readInt() != 0;
4289                     int numRoamingConsortiumIds = in.readInt();
4290                     config.roamingConsortiumIds = new long[numRoamingConsortiumIds];
4291                     for (int i = 0; i < numRoamingConsortiumIds; i++) {
4292                         config.roamingConsortiumIds[i] = in.readLong();
4293                     }
4294                     config.preSharedKey = in.readString();
4295                     for (int i = 0; i < config.wepKeys.length; i++) {
4296                         config.wepKeys[i] = in.readString();
4297                     }
4298                     config.wepTxKeyIndex = in.readInt();
4299                     config.priority = in.readInt();
4300                     config.mDeletionPriority = in.readInt();
4301                     config.hiddenSSID = in.readInt() != 0;
4302                     config.requirePmf = in.readInt() != 0;
4303                     config.updateIdentifier = in.readString();
4304 
4305                     config.allowedKeyManagement = readBitSet(in);
4306                     config.allowedProtocols = readBitSet(in);
4307                     config.allowedAuthAlgorithms = readBitSet(in);
4308                     config.allowedPairwiseCiphers = readBitSet(in);
4309                     config.allowedGroupCiphers = readBitSet(in);
4310                     config.allowedGroupManagementCiphers = readBitSet(in);
4311                     config.allowedSuiteBCiphers = readBitSet(in);
4312 
4313                     int numSecurityParams = in.readInt();
4314                     for (int i = 0; i < numSecurityParams; i++) {
4315                         config.mSecurityParamsList.add(
4316                                 in.readParcelable(SecurityParams.class.getClassLoader()));
4317                     }
4318 
4319                     config.enterpriseConfig = in.readParcelable(
4320                             WifiEnterpriseConfig.class.getClassLoader());
4321                     config.setIpConfiguration(
4322                             in.readParcelable(IpConfiguration.class.getClassLoader()));
4323                     config.dhcpServer = in.readString();
4324                     config.defaultGwMacAddress = in.readString();
4325                     config.validatedInternetAccess = in.readInt() != 0;
4326                     config.isLegacyPasspointConfig = in.readInt() != 0;
4327                     config.ephemeral = in.readInt() != 0;
4328                     config.trusted = in.readInt() != 0;
4329                     config.oemPaid = in.readInt() != 0;
4330                     config.oemPrivate = in.readInt() != 0;
4331                     config.carrierMerged = in.readInt() != 0;
4332                     config.fromWifiNetworkSuggestion = in.readInt() != 0;
4333                     config.fromWifiNetworkSpecifier = in.readInt() != 0;
4334                     config.meteredHint = in.readInt() != 0;
4335                     config.mIsRepeaterEnabled = in.readBoolean();
4336                     config.meteredOverride = in.readInt();
4337                     config.useExternalScores = in.readInt() != 0;
4338                     config.creatorUid = in.readInt();
4339                     config.lastConnectUid = in.readInt();
4340                     config.lastUpdateUid = in.readInt();
4341                     config.creatorName = in.readString();
4342                     config.lastUpdateName = in.readString();
4343                     config.numScorerOverride = in.readInt();
4344                     config.numScorerOverrideAndSwitchedNetwork = in.readInt();
4345                     config.numAssociation = in.readInt();
4346                     config.allowAutojoin = in.readBoolean();
4347                     config.numNoInternetAccessReports = in.readInt();
4348                     config.noInternetAccessExpected = in.readInt() != 0;
4349                     config.shared = in.readInt() != 0;
4350                     config.mPasspointManagementObjectTree = in.readString();
4351                     config.recentFailure.setAssociationStatus(in.readInt(), in.readLong());
4352                     config.mRandomizedMacAddress = in.readParcelable(
4353                             MacAddress.class.getClassLoader());
4354                     config.macRandomizationSetting = in.readInt();
4355                     config.mIsSendDhcpHostnameEnabled = in.readBoolean();
4356                     config.osu = in.readInt() != 0;
4357                     config.randomizedMacExpirationTimeMs = in.readLong();
4358                     config.randomizedMacLastModifiedTimeMs = in.readLong();
4359                     config.carrierId = in.readInt();
4360                     config.mPasspointUniqueId = in.readString();
4361                     config.subscriptionId = in.readInt();
4362                     config.restricted = in.readBoolean();
4363                     config.mSubscriptionGroup = in.readParcelable(
4364                             ParcelUuid.class.getClassLoader());
4365                     config.mBssidAllowlist = in.readArrayList(MacAddress.class.getClassLoader());
4366                     config.mIsDppConfigurator = in.readBoolean();
4367                     config.mDppPrivateEcKey = in.createByteArray();
4368                     if (config.mDppPrivateEcKey == null) {
4369                         config.mDppPrivateEcKey = new byte[0];
4370                     }
4371                     config.mDppConnector = in.createByteArray();
4372                     if (config.mDppConnector == null) {
4373                         config.mDppConnector = new byte[0];
4374                     }
4375                     config.mDppCSignKey = in.createByteArray();
4376                     if (config.mDppCSignKey == null) {
4377                         config.mDppCSignKey = new byte[0];
4378                     }
4379                     config.mDppNetAccessKey = in.createByteArray();
4380                     if (config.mDppNetAccessKey == null) {
4381                         config.mDppNetAccessKey = new byte[0];
4382                     }
4383                     config.isCurrentlyConnected = in.readBoolean();
4384                     config.mIsUserSelected = in.readBoolean();
4385                     config.mHasPreSharedKeyChanged = in.readBoolean();
4386                     config.mEncryptedPreSharedKey = in.createByteArray();
4387                     if (config.mEncryptedPreSharedKey == null) {
4388                         config.mEncryptedPreSharedKey = new byte[0];
4389                     }
4390                     config.mEncryptedPreSharedKeyIv = in.createByteArray();
4391                     if (config.mEncryptedPreSharedKeyIv == null) {
4392                         config.mEncryptedPreSharedKeyIv = new byte[0];
4393                     }
4394                     config.mIpProvisioningTimedOut = in.readBoolean();
4395                     config.mVendorData = ParcelUtil.readOuiKeyedDataList(in);
4396                     config.mWifi7Enabled = in.readBoolean();
4397                     return config;
4398                 }
4399 
4400                 public WifiConfiguration[] newArray(int size) {
4401                     return new WifiConfiguration[size];
4402                 }
4403             };
4404 
4405     /**
4406      * Passpoint Unique identifier
4407      * @hide
4408      */
4409     private String mPasspointUniqueId = null;
4410 
4411     /**
4412      * Set the Passpoint unique identifier
4413      * @param uniqueId Passpoint unique identifier to be set
4414      * @hide
4415      */
setPasspointUniqueId(String uniqueId)4416     public void setPasspointUniqueId(String uniqueId) {
4417         mPasspointUniqueId = uniqueId;
4418     }
4419 
4420     /**
4421      * Set the Passpoint unique identifier
4422      * @hide
4423      */
getPasspointUniqueId()4424     public String getPasspointUniqueId() {
4425         return mPasspointUniqueId;
4426     }
4427 
4428     /**
4429      * If network is one of the most recently connected.
4430      * For framework internal use only. Do not parcel.
4431      * @hide
4432      */
4433     public boolean isMostRecentlyConnected = false;
4434 
4435     /**
4436      * Whether the network is currently connected or not.
4437      * Note: May be true even if {@link #status} is not CURRENT, since a config
4438      *       can be connected, but disabled for network selection.
4439      * TODO (b/235236813): This field may be redundant, since we have information
4440      *       like {@link #status} and quality network selection status. May need
4441      *       to clean up the fields used for network selection.
4442      * @hide
4443      */
4444     public boolean isCurrentlyConnected = false;
4445 
4446     private boolean mIsUserSelected = false;
4447 
4448     /**
4449      * Sets whether the network is connected by user selection or not.
4450      * @hide
4451      */
setIsUserSelected(boolean isUserSelected)4452     public boolean setIsUserSelected(boolean isUserSelected) {
4453         return mIsUserSelected = isUserSelected;
4454     }
4455 
4456     /**
4457      * Whether the network is connected by user selection or not.
4458      * @hide
4459      */
isUserSelected()4460     public boolean isUserSelected() {
4461         return mIsUserSelected;
4462     }
4463 
4464     /**
4465      * Whether the key mgmt indicates if the WifiConfiguration needs a preSharedKey or not.
4466      * @return true if preSharedKey is needed, false otherwise.
4467      * @hide
4468      */
needsPreSharedKey()4469     public boolean needsPreSharedKey() {
4470         for (SecurityParams params : mSecurityParamsList) {
4471             if (params.isSecurityType(SECURITY_TYPE_PSK)
4472                     || params.isSecurityType(SECURITY_TYPE_SAE)
4473                     || params.isSecurityType(SECURITY_TYPE_WAPI_PSK)) {
4474                 return true;
4475             }
4476         }
4477         return false;
4478     }
4479 
4480     /**
4481      * Return if the encrypted data is present
4482      * @return true if encrypted data is present
4483      * @hide
4484      */
hasEncryptedPreSharedKey()4485     public boolean hasEncryptedPreSharedKey() {
4486         if (mEncryptedPreSharedKey == null || mEncryptedPreSharedKeyIv == null) return false;
4487         return !(mEncryptedPreSharedKey.length == 0 && mEncryptedPreSharedKeyIv.length == 0);
4488     }
4489 
4490     /**
4491      * Set the encrypted data for preSharedKey
4492      * @param encryptedPreSharedKey encrypted preSharedKey
4493      * @param encryptedPreSharedKeyIv encrypted preSharedKey
4494      * @hide
4495      */
setEncryptedPreSharedKey(byte[] encryptedPreSharedKey, byte[] encryptedPreSharedKeyIv)4496     public void setEncryptedPreSharedKey(byte[] encryptedPreSharedKey,
4497             byte[] encryptedPreSharedKeyIv) {
4498         mEncryptedPreSharedKey = encryptedPreSharedKey;
4499         mEncryptedPreSharedKeyIv = encryptedPreSharedKeyIv;
4500     }
4501 
4502     /**
4503      * Get the encrypted data
4504      *
4505      * @return encrypted data of the WifiConfiguration
4506      * @hide
4507      */
getEncryptedPreSharedKey()4508     public byte[] getEncryptedPreSharedKey() {
4509         return mEncryptedPreSharedKey;
4510     }
4511 
4512     /**
4513      * Get the encrypted data IV
4514      *
4515      * @return encrypted data IV of the WifiConfiguration
4516      * @hide
4517      */
getEncryptedPreSharedKeyIv()4518     public byte[] getEncryptedPreSharedKeyIv() {
4519         return mEncryptedPreSharedKeyIv;
4520     }
4521 
4522     /**
4523      * Check whether the configuration's password has changed.
4524      * If true, the encrypted data is no longer valid.
4525      *
4526      * @return true if preSharedKey encryption is needed, false otherwise.
4527      * @hide
4528      */
hasPreSharedKeyChanged()4529     public boolean hasPreSharedKeyChanged() {
4530         return mHasPreSharedKeyChanged;
4531     }
4532 
4533     /**
4534      * Set whether the WifiConfiguration needs a preSharedKey encryption.
4535      *
4536      * @param changed true if preSharedKey is changed, false otherwise.
4537      * @hide
4538      */
setHasPreSharedKeyChanged(boolean changed)4539     public void setHasPreSharedKeyChanged(boolean changed) {
4540         mHasPreSharedKeyChanged = changed;
4541         if (mHasPreSharedKeyChanged) {
4542             mEncryptedPreSharedKey = new byte[0];
4543             mEncryptedPreSharedKeyIv = new byte[0];
4544         }
4545     }
4546 
4547     /**
4548      * Get a unique key which represent this Wi-Fi configuration profile. If two profiles are for
4549      * the same Wi-Fi network, but from different providers (apps, carriers, or data subscriptions),
4550      * they would have different keys.
4551      * @return a unique key which represent this profile.
4552      * @hide
4553      */
4554     @SystemApi
getProfileKey()4555     @NonNull public String getProfileKey() {
4556         if (!SdkLevel.isAtLeastS()) {
4557             return getKey();
4558         }
4559         if (mPasspointUniqueId != null) {
4560             return mPasspointUniqueId;
4561         }
4562 
4563         String key = getSsidAndSecurityTypeString();
4564         if (!shared) {
4565             key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier();
4566         }
4567         if (fromWifiNetworkSuggestion) {
4568             key += "_" + creatorName + "-" + carrierId + "-" + subscriptionId;
4569         }
4570 
4571         return key;
4572     }
4573 
4574     /**
4575      * Get the default security type string.
4576      * @hide
4577      */
getDefaultSecurityType()4578     public String getDefaultSecurityType() {
4579         String key;
4580         if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
4581             key = KeyMgmt.strings[KeyMgmt.WPA_PSK];
4582         } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
4583                 || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
4584             if (isWpa3EnterpriseConfiguration()) {
4585                 key = "WPA3_EAP";
4586             } else {
4587                 key = KeyMgmt.strings[KeyMgmt.WPA_EAP];
4588             }
4589         } else if (wepTxKeyIndex >= 0 && wepTxKeyIndex < wepKeys.length
4590                 && wepKeys[wepTxKeyIndex] != null) {
4591             key = "WEP";
4592         } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
4593             key = KeyMgmt.strings[KeyMgmt.OWE];
4594         } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
4595             key = KeyMgmt.strings[KeyMgmt.SAE];
4596         } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
4597             key = KeyMgmt.strings[KeyMgmt.SUITE_B_192];
4598         } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) {
4599             key = KeyMgmt.strings[KeyMgmt.WAPI_PSK];
4600         } else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) {
4601             key = KeyMgmt.strings[KeyMgmt.WAPI_CERT];
4602         } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) {
4603             key = KeyMgmt.strings[KeyMgmt.OSEN];
4604         } else if (allowedKeyManagement.get(KeyMgmt.DPP)) {
4605             key = KeyMgmt.strings[KeyMgmt.DPP];
4606         } else {
4607             key = KeyMgmt.strings[KeyMgmt.NONE];
4608         }
4609         return key;
4610     }
4611 
4612     /**
4613      * Get the security type name.
4614      *
4615      * @param securityType One of the following security types:
4616      * {@link #SECURITY_TYPE_OPEN},
4617      * {@link #SECURITY_TYPE_WEP},
4618      * {@link #SECURITY_TYPE_PSK},
4619      * {@link #SECURITY_TYPE_EAP},
4620      * {@link #SECURITY_TYPE_SAE},
4621      * {@link #SECURITY_TYPE_OWE},
4622      * {@link #SECURITY_TYPE_WAPI_PSK},
4623      * {@link #SECURITY_TYPE_WAPI_CERT},
4624      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
4625      * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
4626      * {@link #SECURITY_TYPE_PASSPOINT_R1_R2},
4627      * {@link #SECURITY_TYPE_PASSPOINT_R3},
4628      * or {@link #SECURITY_TYPE_DPP}.
4629      * @return the name of the given type.
4630      * @hide
4631      */
getSecurityTypeName(@ecurityType int securityType)4632     public static String getSecurityTypeName(@SecurityType int securityType) {
4633         if (securityType < SECURITY_TYPE_OPEN || SECURITY_TYPE_NUM < securityType) {
4634             return "unknown";
4635         }
4636         return SECURITY_TYPE_NAMES[securityType];
4637     }
4638 
4639     /**
4640      * Returns the key for storing the data usage bucket.
4641      *
4642      * Note: DO NOT change this function. It is used to be a key to store Wi-Fi data usage data.
4643      * Create a new function if we plan to change the key for Wi-Fi data usage and add the new key
4644      * to {@link #getAllNetworkKeys()}.
4645      *
4646      * @param securityType the security type corresponding to the target network.
4647      * @hide
4648      */
getNetworkKeyFromSecurityType(@ecurityType int securityType)4649     public String getNetworkKeyFromSecurityType(@SecurityType int securityType) {
4650         if (mPasspointUniqueId != null) {
4651             // It might happen that there are two connections which use the same passpoint
4652             // coniguration but different sim card (maybe same carriers?). Add subscriptionId to be
4653             // the part of key to separate data in usage bucket.
4654             // But now we only show one WifiConfiguration entry in Wifi picker for this case.
4655             // It means that user only have a way to query usage with configuration on default SIM.
4656             // (We always connect to network with default SIM). So returns the key with associated
4657             // subscriptionId (the default one) first.
4658             return subscriptionId + "-" + mPasspointUniqueId;
4659         } else {
4660             String key = (!TextUtils.isEmpty(SSID) && SSID.charAt(0) != '\"'
4661                     ? SSID.toLowerCase() : SSID) + getSecurityTypeName(securityType);
4662             if (!shared) {
4663                 key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier();
4664             }
4665             if (fromWifiNetworkSuggestion) {
4666                 key += "_" + creatorName + "-" + carrierId + "-" + subscriptionId;
4667             }
4668             return key;
4669         }
4670     }
4671 
4672     /**
4673      * Returns a list of all persistable network keys corresponding to this configuration.
4674      * There may be multiple keys since they are security-type specific and a configuration may
4675      * support multiple security types. The persistable key of a specific network connection may
4676      * be obtained from {@link WifiInfo#getNetworkKey()}.
4677      * An example of usage of such persistable network keys is to query the Wi-Fi data usage
4678      * corresponding to this configuration. See {@code NetworkTemplate} to know the detail.
4679      *
4680      * @hide
4681      */
4682     @SystemApi
4683     @NonNull
getAllNetworkKeys()4684     public Set<String> getAllNetworkKeys() {
4685         Set<String> keys = new HashSet<>();
4686         for (SecurityParams securityParam : mSecurityParamsList) {
4687             keys.add(getNetworkKeyFromSecurityType(securityParam.getSecurityType()));
4688         }
4689         return keys;
4690     }
4691 
4692     /**
4693      * Set the subscription group uuid associated with current configuration.
4694      * @hide
4695      */
setSubscriptionGroup(@ullable ParcelUuid subscriptionGroup)4696     public void setSubscriptionGroup(@Nullable ParcelUuid subscriptionGroup) {
4697         this.mSubscriptionGroup = subscriptionGroup;
4698     }
4699 
4700     /**
4701      * Get the subscription group uuid associated with current configuration.
4702      * @hide
4703      */
getSubscriptionGroup()4704     public @Nullable ParcelUuid getSubscriptionGroup() {
4705         return this.mSubscriptionGroup;
4706     }
4707 
4708     /**
4709      * Return the vendor-provided configuration data, if it exists. See also {@link
4710      * #setVendorData(List)}
4711      *
4712      * @return Vendor configuration data, or empty list if it does not exist.
4713      * @hide
4714      */
4715     @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
4716     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
4717     @NonNull
4718     @SystemApi
getVendorData()4719     public List<OuiKeyedData> getVendorData() {
4720         if (!SdkLevel.isAtLeastV()) {
4721             throw new UnsupportedOperationException();
4722         }
4723         return mVendorData;
4724     }
4725 
4726     /**
4727      * Set additional vendor-provided configuration data.
4728      *
4729      * Setting this field requires the MANAGE_WIFI_NETWORK_SELECTION permission. Otherwise,
4730      * if this data is set, the configuration will be rejected upon add or update.
4731      *
4732      * @param vendorData List of {@link OuiKeyedData} containing the vendor-provided
4733      *     configuration data. Note that multiple elements with the same OUI are allowed.
4734      * @hide
4735      */
4736     @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
4737     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
4738     @SystemApi
setVendorData(@onNull List<OuiKeyedData> vendorData)4739     public void setVendorData(@NonNull List<OuiKeyedData> vendorData) {
4740         if (!SdkLevel.isAtLeastV()) {
4741             throw new UnsupportedOperationException();
4742         }
4743         Objects.requireNonNull(vendorData);
4744         mVendorData = new ArrayList<>(vendorData);
4745     }
4746 
4747     /**
4748      * Whether Wi-Fi 7 is enabled for this network.
4749      *
4750      * @return true if enabled; false otherwise
4751      * @hide
4752      */
4753     @SystemApi
4754     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
isWifi7Enabled()4755     public boolean isWifi7Enabled() {
4756         return mWifi7Enabled;
4757     }
4758 
4759     /**
4760      * Sets whether Wi-Fi 7 is enabled for this network.
4761      *
4762      * @param enabled true if enabled; false otherwise
4763      * @hide
4764      */
4765     @SystemApi
4766     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
setWifi7Enabled(boolean enabled)4767     public void setWifi7Enabled(boolean enabled) {
4768         mWifi7Enabled = enabled;
4769     }
4770 }
4771