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