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