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