• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.wifi;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.SystemApi;
22 import android.annotation.UnsupportedAppUsage;
23 import android.content.pm.PackageManager;
24 import android.net.IpConfiguration;
25 import android.net.IpConfiguration.ProxySettings;
26 import android.net.MacAddress;
27 import android.net.NetworkSpecifier;
28 import android.net.ProxyInfo;
29 import android.net.StaticIpConfiguration;
30 import android.net.Uri;
31 import android.os.Build;
32 import android.os.Parcel;
33 import android.os.Parcelable;
34 import android.os.SystemClock;
35 import android.os.UserHandle;
36 import android.text.TextUtils;
37 import android.util.BackupUtils;
38 import android.util.Log;
39 import android.util.TimeUtils;
40 
41 import java.io.ByteArrayOutputStream;
42 import java.io.DataInputStream;
43 import java.io.DataOutputStream;
44 import java.io.IOException;
45 import java.lang.annotation.Retention;
46 import java.lang.annotation.RetentionPolicy;
47 import java.util.Arrays;
48 import java.util.BitSet;
49 import java.util.HashMap;
50 
51 /**
52  * A class representing a configured Wi-Fi network, including the
53  * security configuration.
54  *
55  * @deprecated Use {@link WifiNetworkSpecifier.Builder} to create {@link NetworkSpecifier} and
56  * {@link WifiNetworkSuggestion.Builder} to create {@link WifiNetworkSuggestion}. This will become a
57  * system use only object in the future.
58  */
59 @Deprecated
60 public class WifiConfiguration implements Parcelable {
61     private static final String TAG = "WifiConfiguration";
62     /**
63      * Current Version of the Backup Serializer.
64     */
65     private static final int BACKUP_VERSION = 3;
66     /** {@hide} */
67     public static final String ssidVarName = "ssid";
68     /** {@hide} */
69     public static final String bssidVarName = "bssid";
70     /** {@hide} */
71     public static final String pskVarName = "psk";
72     /** {@hide} */
73     @Deprecated
74     @UnsupportedAppUsage
75     public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" };
76     /** {@hide} */
77     @Deprecated
78     public static final String wepTxKeyIdxVarName = "wep_tx_keyidx";
79     /** {@hide} */
80     public static final String priorityVarName = "priority";
81     /** {@hide} */
82     public static final String hiddenSSIDVarName = "scan_ssid";
83     /** {@hide} */
84     public static final String pmfVarName = "ieee80211w";
85     /** {@hide} */
86     public static final String updateIdentiferVarName = "update_identifier";
87     /** {@hide} */
88     public static final int INVALID_NETWORK_ID = -1;
89     /** {@hide} */
90     public static final int LOCAL_ONLY_NETWORK_ID = -2;
91 
92     /** {@hide} */
93     private String mPasspointManagementObjectTree;
94     /** {@hide} */
95     private static final int MAXIMUM_RANDOM_MAC_GENERATION_RETRY = 3;
96 
97     /**
98      * Recognized key management schemes.
99      */
100     public static class KeyMgmt {
KeyMgmt()101         private KeyMgmt() { }
102 
103         /** WPA is not used; plaintext or static WEP could be used. */
104         public static final int NONE = 0;
105         /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */
106         public static final int WPA_PSK = 1;
107         /** WPA using EAP authentication. Generally used with an external authentication server. */
108         public static final int WPA_EAP = 2;
109         /** IEEE 802.1X using EAP authentication and (optionally) dynamically
110          * generated WEP keys. */
111         public static final int IEEE8021X = 3;
112 
113         /** WPA2 pre-shared key for use with soft access point
114           * (requires {@code preSharedKey} to be specified).
115           * @hide
116           */
117         @SystemApi
118         public static final int WPA2_PSK = 4;
119         /**
120          * Hotspot 2.0 r2 OSEN:
121          * @hide
122          */
123         public static final int OSEN = 5;
124 
125         /**
126          * IEEE 802.11r Fast BSS Transition with PSK authentication.
127          * @hide
128          */
129         public static final int FT_PSK = 6;
130 
131         /**
132          * IEEE 802.11r Fast BSS Transition with EAP authentication.
133          * @hide
134          */
135         public static final int FT_EAP = 7;
136 
137         /**
138          * Simultaneous Authentication of Equals
139          */
140         public static final int SAE = 8;
141 
142         /**
143          * Opportunististic Wireless Encryption
144          */
145         public static final int OWE = 9;
146 
147         /**
148          * SUITE_B_192 192 bit level
149          */
150         public static final int SUITE_B_192 = 10;
151 
152         /**
153          * WPA pre-shared key with stronger SHA256-based algorithms.
154          * @hide
155          */
156         public static final int WPA_PSK_SHA256 = 11;
157 
158         /**
159          * WPA using EAP authentication with stronger SHA256-based algorithms.
160          * @hide
161          */
162         public static final int WPA_EAP_SHA256 = 12;
163 
164         public static final String varName = "key_mgmt";
165 
166         public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP",
167                 "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP",
168                 "SAE", "OWE", "SUITE_B_192", "WPA_PSK_SHA256", "WPA_EAP_SHA256" };
169     }
170 
171     /**
172      * Recognized security protocols.
173      */
174     public static class Protocol {
Protocol()175         private Protocol() { }
176 
177         /** WPA/IEEE 802.11i/D3.0
178          * @deprecated Due to security and performance limitations, use of WPA-1 networks
179          * is discouraged. WPA-2 (RSN) should be used instead. */
180         @Deprecated
181         public static final int WPA = 0;
182         /** RSN WPA2/WPA3/IEEE 802.11i */
183         public static final int RSN = 1;
184         /** HS2.0 r2 OSEN
185          * @hide
186          */
187         public static final int OSEN = 2;
188 
189         public static final String varName = "proto";
190 
191         public static final String[] strings = { "WPA", "RSN", "OSEN" };
192     }
193 
194     /**
195      * Recognized IEEE 802.11 authentication algorithms.
196      */
197     public static class AuthAlgorithm {
AuthAlgorithm()198         private AuthAlgorithm() { }
199 
200         /** Open System authentication (required for WPA/WPA2) */
201         public static final int OPEN = 0;
202         /** Shared Key authentication (requires static WEP keys)
203          * @deprecated Due to security and performance limitations, use of WEP networks
204          * is discouraged. */
205         @Deprecated
206         public static final int SHARED = 1;
207         /** LEAP/Network EAP (only used with LEAP) */
208         public static final int LEAP = 2;
209 
210         public static final String varName = "auth_alg";
211 
212         public static final String[] strings = { "OPEN", "SHARED", "LEAP" };
213     }
214 
215     /**
216      * Recognized pairwise ciphers for WPA.
217      */
218     public static class PairwiseCipher {
PairwiseCipher()219         private PairwiseCipher() { }
220 
221         /** Use only Group keys (deprecated) */
222         public static final int NONE = 0;
223         /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
224          * @deprecated Due to security and performance limitations, use of WPA-1 networks
225          * is discouraged. WPA-2 (RSN) should be used instead. */
226         @Deprecated
227         public static final int TKIP = 1;
228         /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
229         public static final int CCMP = 2;
230         /**
231          * AES in Galois/Counter Mode
232          */
233         public static final int GCMP_256 = 3;
234 
235         public static final String varName = "pairwise";
236 
237         public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256" };
238     }
239 
240     /**
241      * Recognized group ciphers.
242      * <pre>
243      * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
244      * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
245      * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
246      * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
247      * GCMP_256 = AES in Galois/Counter Mode
248      * </pre>
249      */
250     public static class GroupCipher {
GroupCipher()251         private GroupCipher() { }
252 
253         /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
254          * @deprecated Due to security and performance limitations, use of WEP networks
255          * is discouraged. */
256         @Deprecated
257         public static final int WEP40 = 0;
258         /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
259          * @deprecated Due to security and performance limitations, use of WEP networks
260          * is discouraged. */
261         @Deprecated
262         public static final int WEP104 = 1;
263         /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
264         public static final int TKIP = 2;
265         /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
266         public static final int CCMP = 3;
267         /** Hotspot 2.0 r2 OSEN
268          * @hide
269          */
270         public static final int GTK_NOT_USED = 4;
271         /**
272          * AES in Galois/Counter Mode
273          */
274         public static final int GCMP_256 = 5;
275 
276         public static final String varName = "group";
277 
278         public static final String[] strings =
279                 { /* deprecated */ "WEP40", /* deprecated */ "WEP104",
280                         "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256" };
281     }
282 
283     /**
284      * Recognized group management ciphers.
285      * <pre>
286      * BIP_CMAC_256 = Cipher-based Message Authentication Code 256 bits
287      * BIP_GMAC_128 = Galois Message Authentication Code 128 bits
288      * BIP_GMAC_256 = Galois Message Authentication Code 256 bits
289      * </pre>
290      */
291     public static class GroupMgmtCipher {
GroupMgmtCipher()292         private GroupMgmtCipher() { }
293 
294         /** CMAC-256 = Cipher-based Message Authentication Code */
295         public static final int BIP_CMAC_256 = 0;
296 
297         /** GMAC-128 = Galois Message Authentication Code */
298         public static final int BIP_GMAC_128 = 1;
299 
300         /** GMAC-256 = Galois Message Authentication Code */
301         public static final int BIP_GMAC_256 = 2;
302 
303         private static final String varName = "groupMgmt";
304 
305         private static final String[] strings = { "BIP_CMAC_256",
306                 "BIP_GMAC_128", "BIP_GMAC_256"};
307     }
308 
309     /**
310      * Recognized suiteB ciphers.
311      * <pre>
312      * ECDHE_ECDSA
313      * ECDHE_RSA
314      * </pre>
315      * @hide
316      */
317     public static class SuiteBCipher {
SuiteBCipher()318         private SuiteBCipher() { }
319 
320         /** Diffie-Hellman with Elliptic Curve_ECDSA signature */
321         public static final int ECDHE_ECDSA = 0;
322 
323         /** Diffie-Hellman with_RSA signature */
324         public static final int ECDHE_RSA = 1;
325 
326         private static final String varName = "SuiteB";
327 
328         private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" };
329     }
330 
331     /** Possible status of a network configuration. */
332     public static class Status {
Status()333         private Status() { }
334 
335         /** this is the network we are currently connected to */
336         public static final int CURRENT = 0;
337         /** supplicant will not attempt to use this network */
338         public static final int DISABLED = 1;
339         /** supplicant will consider this network available for association */
340         public static final int ENABLED = 2;
341 
342         public static final String[] strings = { "current", "disabled", "enabled" };
343     }
344 
345     /**
346      * Security types we support.
347      */
348     /** @hide */
349     public static final int SECURITY_TYPE_OPEN = 0;
350     /** @hide */
351     public static final int SECURITY_TYPE_WEP = 1;
352     /** @hide */
353     public static final int SECURITY_TYPE_PSK = 2;
354     /** @hide */
355     public static final int SECURITY_TYPE_EAP = 3;
356     /** @hide */
357     public static final int SECURITY_TYPE_SAE = 4;
358     /** @hide */
359     public static final int SECURITY_TYPE_EAP_SUITE_B = 5;
360     /** @hide */
361     public static final int SECURITY_TYPE_OWE = 6;
362 
363     /** @hide */
364     @Retention(RetentionPolicy.SOURCE)
365     @IntDef(prefix = { "SECURITY_TYPE_" }, value = {
366             SECURITY_TYPE_OPEN,
367             SECURITY_TYPE_WEP,
368             SECURITY_TYPE_PSK,
369             SECURITY_TYPE_EAP,
370             SECURITY_TYPE_SAE,
371             SECURITY_TYPE_EAP_SUITE_B,
372             SECURITY_TYPE_OWE
373     })
374     public @interface SecurityType {}
375 
376     /**
377      * @hide
378      * Set security params (sets the various bitsets exposed in WifiConfiguration).
379      *
380      * @param securityType One of the security types from {@link SecurityType}.
381      */
setSecurityParams(@ecurityType int securityType)382     public void setSecurityParams(@SecurityType int securityType) {
383         // Clear all the bitsets.
384         allowedKeyManagement.clear();
385         allowedProtocols.clear();
386         allowedAuthAlgorithms.clear();
387         allowedPairwiseCiphers.clear();
388         allowedGroupCiphers.clear();
389         allowedGroupManagementCiphers.clear();
390         allowedSuiteBCiphers.clear();
391 
392         switch (securityType) {
393             case SECURITY_TYPE_OPEN:
394                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
395                 break;
396             case SECURITY_TYPE_WEP:
397                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
398                 allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
399                 allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
400                 break;
401             case SECURITY_TYPE_PSK:
402                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
403                 break;
404             case SECURITY_TYPE_EAP:
405                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
406                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
407                 break;
408             case SECURITY_TYPE_SAE:
409                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
410                 requirePMF = true;
411                 break;
412             case SECURITY_TYPE_EAP_SUITE_B:
413                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
414                 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
415                 allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
416                 // Note: allowedSuiteBCiphers bitset will be set by the service once the
417                 // certificates are attached to this profile
418                 requirePMF = true;
419                 break;
420             case SECURITY_TYPE_OWE:
421                 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
422                 requirePMF = true;
423                 break;
424             default:
425                 throw new IllegalArgumentException("unknown security type " + securityType);
426         }
427     }
428 
429     /** @hide */
430     public static final int UNKNOWN_UID = -1;
431 
432     /**
433      * The ID number that the supplicant uses to identify this
434      * network configuration entry. This must be passed as an argument
435      * to most calls into the supplicant.
436      */
437     public int networkId;
438 
439     // Fixme We need remove this field to use only Quality network selection status only
440     /**
441      * The current status of this network configuration entry.
442      * @see Status
443      */
444     public int status;
445 
446     /**
447      * The network's SSID. Can either be a UTF-8 string,
448      * which must be enclosed in double quotation marks
449      * (e.g., {@code "MyNetwork"}), or a string of
450      * hex digits, which are not enclosed in quotes
451      * (e.g., {@code 01a243f405}).
452      */
453     public String SSID;
454 
455     /**
456      * When set, this network configuration entry should only be used when
457      * associating with the AP having the specified BSSID. The value is
458      * a string in the format of an Ethernet MAC address, e.g.,
459      * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
460      */
461     public String BSSID;
462 
463     /**
464      * 2GHz band.
465      * @hide
466      */
467     public static final int AP_BAND_2GHZ = 0;
468 
469     /**
470      * 5GHz band.
471      * @hide
472      */
473     public static final int AP_BAND_5GHZ = 1;
474 
475     /**
476      * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
477      * operating country code and current radio conditions.
478      * @hide
479      */
480     public static final int AP_BAND_ANY = -1;
481 
482     /**
483      * The band which AP resides on
484      * -1:Any 0:2G 1:5G
485      * By default, 2G is chosen
486      * @hide
487      */
488     @UnsupportedAppUsage
489     public int apBand = AP_BAND_2GHZ;
490 
491     /**
492      * The channel which AP resides on,currently, US only
493      * 2G  1-11
494      * 5G  36,40,44,48,149,153,157,161,165
495      * 0 - find a random available channel according to the apBand
496      * @hide
497      */
498     @UnsupportedAppUsage
499     public int apChannel = 0;
500 
501     /**
502      * Pre-shared key for use with WPA-PSK. Either an ASCII string enclosed in
503      * double quotation marks (e.g., {@code "abcdefghij"} for PSK passphrase or
504      * a string of 64 hex digits for raw PSK.
505      * <p/>
506      * When the value of this key is read, the actual key is
507      * not returned, just a "*" if the key has a value, or the null
508      * string otherwise.
509      */
510     public String preSharedKey;
511 
512     /**
513      * Four WEP keys. For each of the four values, provide either an ASCII
514      * string enclosed in double quotation marks (e.g., {@code "abcdef"}),
515      * a string of hex digits (e.g., {@code 0102030405}), or an empty string
516      * (e.g., {@code ""}).
517      * <p/>
518      * When the value of one of these keys is read, the actual key is
519      * not returned, just a "*" if the key has a value, or the null
520      * string otherwise.
521      * @deprecated Due to security and performance limitations, use of WEP networks
522      * is discouraged.
523      */
524     @Deprecated
525     public String[] wepKeys;
526 
527     /** Default WEP key index, ranging from 0 to 3.
528      * @deprecated Due to security and performance limitations, use of WEP networks
529      * is discouraged. */
530     @Deprecated
531     public int wepTxKeyIndex;
532 
533     /**
534      * Priority determines the preference given to a network by {@code wpa_supplicant}
535      * when choosing an access point with which to associate.
536      * @deprecated This field does not exist anymore.
537      */
538     @Deprecated
539     public int priority;
540 
541     /**
542      * This is a network that does not broadcast its SSID, so an
543      * SSID-specific probe request must be used for scans.
544      */
545     public boolean hiddenSSID;
546 
547     /**
548      * This is a network that requries Protected Management Frames (PMF).
549      * @hide
550      */
551     public boolean requirePMF;
552 
553     /**
554      * Update identifier, for Passpoint network.
555      * @hide
556      */
557     public String updateIdentifier;
558 
559     /**
560      * The set of key management protocols supported by this configuration.
561      * See {@link KeyMgmt} for descriptions of the values.
562      * Defaults to WPA-PSK WPA-EAP.
563      */
564     @NonNull
565     public BitSet allowedKeyManagement;
566     /**
567      * The set of security protocols supported by this configuration.
568      * See {@link Protocol} for descriptions of the values.
569      * Defaults to WPA RSN.
570      */
571     @NonNull
572     public BitSet allowedProtocols;
573     /**
574      * The set of authentication protocols supported by this configuration.
575      * See {@link AuthAlgorithm} for descriptions of the values.
576      * Defaults to automatic selection.
577      */
578     @NonNull
579     public BitSet allowedAuthAlgorithms;
580     /**
581      * The set of pairwise ciphers for WPA supported by this configuration.
582      * See {@link PairwiseCipher} for descriptions of the values.
583      * Defaults to CCMP TKIP.
584      */
585     @NonNull
586     public BitSet allowedPairwiseCiphers;
587     /**
588      * The set of group ciphers supported by this configuration.
589      * See {@link GroupCipher} for descriptions of the values.
590      * Defaults to CCMP TKIP WEP104 WEP40.
591      */
592     @NonNull
593     public BitSet allowedGroupCiphers;
594     /**
595      * The set of group management ciphers supported by this configuration.
596      * See {@link GroupMgmtCipher} for descriptions of the values.
597      */
598     @NonNull
599     public BitSet allowedGroupManagementCiphers;
600     /**
601      * The set of SuiteB ciphers supported by this configuration.
602      * To be used for WPA3-Enterprise mode.
603      * See {@link SuiteBCipher} for descriptions of the values.
604      */
605     @NonNull
606     public BitSet allowedSuiteBCiphers;
607     /**
608      * The enterprise configuration details specifying the EAP method,
609      * certificates and other settings associated with the EAP.
610      */
611     public WifiEnterpriseConfig enterpriseConfig;
612 
613     /**
614      * Fully qualified domain name of a Passpoint configuration
615      */
616     public String FQDN;
617 
618     /**
619      * Name of Passpoint credential provider
620      */
621     public String providerFriendlyName;
622 
623     /**
624      * Flag indicating if this network is provided by a home Passpoint provider or a roaming
625      * Passpoint provider.  This flag will be {@code true} if this network is provided by
626      * a home Passpoint provider and {@code false} if is provided by a roaming Passpoint provider
627      * or is a non-Passpoint network.
628      */
629     public boolean isHomeProviderNetwork;
630 
631     /**
632      * Roaming Consortium Id list for Passpoint credential; identifies a set of networks where
633      * Passpoint credential will be considered valid
634      */
635     public long[] roamingConsortiumIds;
636 
637     /**
638      * @hide
639      * This network configuration is visible to and usable by other users on the
640      * same device.
641      */
642     @UnsupportedAppUsage
643     public boolean shared;
644 
645     /**
646      * @hide
647      */
648     @NonNull
649     @UnsupportedAppUsage
650     private IpConfiguration mIpConfiguration;
651 
652     /**
653      * @hide
654      * dhcp server MAC address if known
655      */
656     public String dhcpServer;
657 
658     /**
659      * @hide
660      * default Gateway MAC address if known
661      */
662     @UnsupportedAppUsage
663     public String defaultGwMacAddress;
664 
665     /**
666      * @hide
667      * last time we connected, this configuration had validated internet access
668      */
669     @UnsupportedAppUsage
670     public boolean validatedInternetAccess;
671 
672     /**
673      * @hide
674      * The number of beacon intervals between Delivery Traffic Indication Maps (DTIM)
675      * This value is populated from scan results that contain Beacon Frames, which are infrequent.
676      * The value is not guaranteed to be set or current (Although it SHOULDNT change once set)
677      * Valid values are from 1 - 255. Initialized here as 0, use this to check if set.
678      */
679     public int dtimInterval = 0;
680 
681     /**
682      * Flag indicating if this configuration represents a legacy Passpoint configuration
683      * (Release N or older).  This is used for migrating Passpoint configuration from N to O.
684      * This will no longer be needed after O.
685      * @hide
686      */
687     public boolean isLegacyPasspointConfig = false;
688     /**
689      * @hide
690      * Uid of app creating the configuration
691      */
692     @SystemApi
693     public int creatorUid;
694 
695     /**
696      * @hide
697      * Uid of last app issuing a connection related command
698      */
699     @UnsupportedAppUsage
700     public int lastConnectUid;
701 
702     /**
703      * @hide
704      * Uid of last app modifying the configuration
705      */
706     @SystemApi
707     public int lastUpdateUid;
708 
709     /**
710      * @hide
711      * Universal name for app creating the configuration
712      *    see {@link PackageManager#getNameForUid(int)}
713      */
714     @SystemApi
715     public String creatorName;
716 
717     /**
718      * @hide
719      * Universal name for app updating the configuration
720      *    see {@link PackageManager#getNameForUid(int)}
721      */
722     @SystemApi
723     public String lastUpdateName;
724 
725     /**
726      * @hide
727      * Status of user approval for connection
728      */
729     public int userApproved = USER_UNSPECIFIED;
730 
731     /** The Below RSSI thresholds are used to configure AutoJoin
732      *  - GOOD/LOW/BAD thresholds are used so as to calculate link score
733      *  - UNWANTED_SOFT are used by the blacklisting logic so as to handle
734      *  the unwanted network message coming from CS
735      *  - UNBLACKLIST thresholds are used so as to tweak the speed at which
736      *  the network is unblacklisted (i.e. if
737      *          it is seen with good RSSI, it is blacklisted faster)
738      *  - INITIAL_AUTOJOIN_ATTEMPT, used to determine how close from
739      *  the network we need to be before autojoin kicks in
740      */
741     /** @hide **/
742     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
743     public static int INVALID_RSSI = -127;
744 
745     // States for the userApproved field
746     /**
747      * @hide
748      * User hasn't specified if connection is okay
749      */
750     public static final int USER_UNSPECIFIED = 0;
751     /**
752      * @hide
753      * User has approved this for connection
754      */
755     public static final int USER_APPROVED = 1;
756     /**
757      * @hide
758      * User has banned this from connection
759      */
760     public static final int USER_BANNED = 2;
761     /**
762      * @hide
763      * Waiting for user input
764      */
765     public static final int USER_PENDING = 3;
766 
767     /**
768      * @hide
769      * Number of reports indicating no Internet Access
770      */
771     @UnsupportedAppUsage
772     public int numNoInternetAccessReports;
773 
774     /**
775      * @hide
776      * For debug: date at which the config was last updated
777      */
778     public String updateTime;
779 
780     /**
781      * @hide
782      * For debug: date at which the config was last updated
783      */
784     public String creationTime;
785 
786     /**
787      * @hide
788      * The WiFi configuration is considered to have no internet access for purpose of autojoining
789      * if there has been a report of it having no internet access, and, it never have had
790      * internet access in the past.
791      */
792     @SystemApi
hasNoInternetAccess()793     public boolean hasNoInternetAccess() {
794         return numNoInternetAccessReports > 0 && !validatedInternetAccess;
795     }
796 
797     /**
798      * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a
799      * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to
800      * this configuration and selects "don't ask again".
801      * @hide
802      */
803     @UnsupportedAppUsage
804     public boolean noInternetAccessExpected;
805 
806     /**
807      * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a
808      * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to
809      * this configuration and selects "don't ask again".
810      * @hide
811      */
812     @SystemApi
isNoInternetAccessExpected()813     public boolean isNoInternetAccessExpected() {
814         return noInternetAccessExpected;
815     }
816 
817     /**
818      * This Wifi configuration is expected for OSU(Online Sign Up) of Passpoint Release 2.
819      * @hide
820      */
821     public boolean osu;
822 
823     /**
824      * @hide
825      * Last time the system was connected to this configuration.
826      */
827     public long lastConnected;
828 
829     /**
830      * @hide
831      * Last time the system was disconnected to this configuration.
832      */
833     public long lastDisconnected;
834 
835     /**
836      * Set if the configuration was self added by the framework
837      * This boolean is cleared if we get a connect/save/ update or
838      * any wifiManager command that indicate the user interacted with the configuration
839      * since we will now consider that the configuration belong to him.
840      * @hide
841      */
842     @UnsupportedAppUsage
843     public boolean selfAdded;
844 
845     /**
846      * Set if the configuration was self added by the framework
847      * This boolean is set once and never cleared. It is used
848      * so as we never loose track of who created the
849      * configuration in the first place.
850      * @hide
851      */
852     public boolean didSelfAdd;
853 
854     /**
855      * Peer WifiConfiguration this WifiConfiguration was added for
856      * @hide
857      */
858     public String peerWifiConfiguration;
859 
860     /**
861      * @hide
862      * Indicate that a WifiConfiguration is temporary and should not be saved
863      * nor considered by AutoJoin.
864      */
865     public boolean ephemeral;
866 
867     /**
868      * @hide
869      * Indicate that a WifiConfiguration is temporary and should not be saved
870      * nor considered by AutoJoin.
871      */
872     @SystemApi
isEphemeral()873     public boolean isEphemeral() {
874       return ephemeral;
875     }
876 
877     /**
878      * Indicate whther the network is trusted or not. Networks are considered trusted
879      * if the user explicitly allowed this network connection.
880      * @hide
881      */
882     public boolean trusted;
883 
884     /**
885      * This Wifi configuration is created from a {@link WifiNetworkSuggestion}
886      * @hide
887      */
888     public boolean fromWifiNetworkSuggestion;
889 
890     /**
891      * This Wifi configuration is created from a {@link WifiNetworkSpecifier}
892      * @hide
893      */
894     public boolean fromWifiNetworkSpecifier;
895 
896     /**
897      * Indicates if the creator of this configuration has expressed that it
898      * should be considered metered.
899      *
900      * @see #isMetered(WifiConfiguration, WifiInfo)
901      * @hide
902      */
903     @SystemApi
904     public boolean meteredHint;
905 
906     /** {@hide} */
907     public static final int METERED_OVERRIDE_NONE = 0;
908     /** {@hide} */
909     public static final int METERED_OVERRIDE_METERED = 1;
910     /** {@hide} */
911     public static final int METERED_OVERRIDE_NOT_METERED = 2;
912 
913     /**
914      * Indicates if the end user has expressed an explicit opinion about the
915      * meteredness of this network, such as through the Settings app.
916      * <p>
917      * This should always override any values from {@link #meteredHint} or
918      * {@link WifiInfo#getMeteredHint()}.
919      *
920      * @see #isMetered(WifiConfiguration, WifiInfo)
921      * @hide
922      */
923     public int meteredOverride = METERED_OVERRIDE_NONE;
924 
925     /**
926      * Blend together all the various opinions to decide if the given network
927      * should be considered metered or not.
928      *
929      * @hide
930      */
isMetered(WifiConfiguration config, WifiInfo info)931     public static boolean isMetered(WifiConfiguration config, WifiInfo info) {
932         boolean metered = false;
933         if (info != null && info.getMeteredHint()) {
934             metered = true;
935         }
936         if (config != null && config.meteredHint) {
937             metered = true;
938         }
939         if (config != null
940                 && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) {
941             metered = true;
942         }
943         if (config != null
944                 && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) {
945             metered = false;
946         }
947         return metered;
948     }
949 
950     /**
951      * @hide
952      * Returns true if this WiFi config is for an open network.
953      */
isOpenNetwork()954     public boolean isOpenNetwork() {
955         final int cardinality = allowedKeyManagement.cardinality();
956         final boolean hasNoKeyMgmt = cardinality == 0
957                 || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE)
958                 || allowedKeyManagement.get(KeyMgmt.OWE)));
959 
960         boolean hasNoWepKeys = true;
961         if (wepKeys != null) {
962             for (int i = 0; i < wepKeys.length; i++) {
963                 if (wepKeys[i] != null) {
964                     hasNoWepKeys = false;
965                     break;
966                 }
967             }
968         }
969 
970         return hasNoKeyMgmt && hasNoWepKeys;
971     }
972 
973     /**
974      * @hide
975      * Setting this value will force scan results associated with this configuration to
976      * be included in the bucket of networks that are externally scored.
977      * If not set, associated scan results will be treated as legacy saved networks and
978      * will take precedence over networks in the scored category.
979      */
980     @SystemApi
981     public boolean useExternalScores;
982 
983     /**
984      * @hide
985      * Number of time the scorer overrode a the priority based choice, when comparing two
986      * WifiConfigurations, note that since comparing WifiConfiguration happens very often
987      * potentially at every scan, this number might become very large, even on an idle
988      * system.
989      */
990     @SystemApi
991     public int numScorerOverride;
992 
993     /**
994      * @hide
995      * Number of time the scorer overrode a the priority based choice, and the comparison
996      * triggered a network switch
997      */
998     @SystemApi
999     public int numScorerOverrideAndSwitchedNetwork;
1000 
1001     /**
1002      * @hide
1003      * Number of time we associated to this configuration.
1004      */
1005     @SystemApi
1006     public int numAssociation;
1007 
1008     /**
1009      * @hide
1010      * Use factory MAC when connecting to this network
1011      */
1012     public static final int RANDOMIZATION_NONE = 0;
1013     /**
1014      * @hide
1015      * Generate a randomized MAC once and reuse it for all connections to this network
1016      */
1017     public static final int RANDOMIZATION_PERSISTENT = 1;
1018 
1019     /**
1020      * @hide
1021      * Level of MAC randomization for this network
1022      */
1023     public int macRandomizationSetting = RANDOMIZATION_PERSISTENT;
1024 
1025     /**
1026      * @hide
1027      * Randomized MAC address to use with this particular network
1028      */
1029     @NonNull
1030     private MacAddress mRandomizedMacAddress;
1031 
1032     /**
1033      * @hide
1034      * Checks if the given MAC address can be used for Connected Mac Randomization
1035      * by verifying that it is non-null, unicast, locally assigned, and not default mac.
1036      * @param mac MacAddress to check
1037      * @return true if mac is good to use
1038      */
isValidMacAddressForRandomization(MacAddress mac)1039     public static boolean isValidMacAddressForRandomization(MacAddress mac) {
1040         return mac != null && !mac.isMulticastAddress() && mac.isLocallyAssigned()
1041                 && !MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS).equals(mac);
1042     }
1043 
1044     /**
1045      * @hide
1046      * Returns Randomized MAC address to use with the network.
1047      * If it is not set/valid, creates a new randomized address.
1048      * If it can't generate a valid mac, returns the default MAC.
1049      */
getOrCreateRandomizedMacAddress()1050     public @NonNull MacAddress getOrCreateRandomizedMacAddress() {
1051         int randomMacGenerationCount = 0;
1052         while (!isValidMacAddressForRandomization(mRandomizedMacAddress)
1053                 && randomMacGenerationCount < MAXIMUM_RANDOM_MAC_GENERATION_RETRY) {
1054             mRandomizedMacAddress = MacAddress.createRandomUnicastAddress();
1055             randomMacGenerationCount++;
1056         }
1057 
1058         if (!isValidMacAddressForRandomization(mRandomizedMacAddress)) {
1059             mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS);
1060         }
1061         return mRandomizedMacAddress;
1062     }
1063 
1064     /**
1065      * Returns MAC address set to be the local randomized MAC address.
1066      * Depending on user preference, the device may or may not use the returned MAC address for
1067      * connections to this network.
1068      * <p>
1069      * Information is restricted to Device Owner, Profile Owner, and Carrier apps
1070      * (which will only obtain addresses for configurations which they create). Other callers
1071      * will receive a default "02:00:00:00:00:00" MAC address.
1072      */
getRandomizedMacAddress()1073     public @NonNull MacAddress getRandomizedMacAddress() {
1074         return mRandomizedMacAddress;
1075     }
1076 
1077     /**
1078      * @hide
1079      * @param mac MacAddress to change into
1080      */
setRandomizedMacAddress(@onNull MacAddress mac)1081     public void setRandomizedMacAddress(@NonNull MacAddress mac) {
1082         if (mac == null) {
1083             Log.e(TAG, "setRandomizedMacAddress received null MacAddress.");
1084             return;
1085         }
1086         mRandomizedMacAddress = mac;
1087     }
1088 
1089     /** @hide
1090      * Boost given to RSSI on a home network for the purpose of calculating the score
1091      * This adds stickiness to home networks, as defined by:
1092      * - less than 4 known BSSIDs
1093      * - PSK only
1094      * - TODO: add a test to verify that all BSSIDs are behind same gateway
1095      ***/
1096     public static final int HOME_NETWORK_RSSI_BOOST = 5;
1097 
1098     /**
1099      * @hide
1100      * This class is used to contain all the information and API used for quality network selection
1101      */
1102     public static class NetworkSelectionStatus {
1103         /**
1104          * Quality Network Selection Status enable, temporary disabled, permanently disabled
1105          */
1106         /**
1107          * This network is allowed to join Quality Network Selection
1108          */
1109         public static final int NETWORK_SELECTION_ENABLED = 0;
1110         /**
1111          * network was temporary disabled. Can be re-enabled after a time period expire
1112          */
1113         public static final int NETWORK_SELECTION_TEMPORARY_DISABLED  = 1;
1114         /**
1115          * network was permanently disabled.
1116          */
1117         public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED  = 2;
1118         /**
1119          * Maximum Network selection status
1120          */
1121         public static final int NETWORK_SELECTION_STATUS_MAX = 3;
1122 
1123         /**
1124          * Quality network selection status String (for debug purpose). Use Quality network
1125          * selection status value as index to extec the corresponding debug string
1126          */
1127         public static final String[] QUALITY_NETWORK_SELECTION_STATUS = {
1128                 "NETWORK_SELECTION_ENABLED",
1129                 "NETWORK_SELECTION_TEMPORARY_DISABLED",
1130                 "NETWORK_SELECTION_PERMANENTLY_DISABLED"};
1131 
1132         //Quality Network disabled reasons
1133         /**
1134          * Default value. Means not disabled
1135          */
1136         public static final int NETWORK_SELECTION_ENABLE = 0;
1137         /**
1138          * The starting index for network selection disabled reasons
1139          */
1140         public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1;
1141         /**
1142          * @deprecated it is not used any more.
1143          * This network is disabled because higher layer (>2) network is bad
1144          */
1145         public static final int DISABLED_BAD_LINK = 1;
1146         /**
1147          * This network is disabled because multiple association rejects
1148          */
1149         public static final int DISABLED_ASSOCIATION_REJECTION = 2;
1150         /**
1151          * This network is disabled because multiple authentication failure
1152          */
1153         public static final int DISABLED_AUTHENTICATION_FAILURE = 3;
1154         /**
1155          * This network is disabled because multiple DHCP failure
1156          */
1157         public static final int DISABLED_DHCP_FAILURE = 4;
1158         /**
1159          * This network is disabled because of security network but no credentials
1160          */
1161         public static final int DISABLED_DNS_FAILURE = 5;
1162         /**
1163          * This network is temporarily disabled because it has no Internet access.
1164          */
1165         public static final int DISABLED_NO_INTERNET_TEMPORARY = 6;
1166         /**
1167          * This network is disabled because we started WPS
1168          */
1169         public static final int DISABLED_WPS_START = 7;
1170         /**
1171          * This network is disabled because EAP-TLS failure
1172          */
1173         public static final int DISABLED_TLS_VERSION_MISMATCH = 8;
1174         // Values above are for temporary disablement; values below are for permanent disablement.
1175         /**
1176          * This network is disabled due to absence of user credentials
1177          */
1178         public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 9;
1179         /**
1180          * This network is permanently disabled because it has no Internet access and user does not
1181          * want to stay connected.
1182          */
1183         public static final int DISABLED_NO_INTERNET_PERMANENT = 10;
1184         /**
1185          * This network is disabled due to WifiManager disable it explicitly
1186          */
1187         public static final int DISABLED_BY_WIFI_MANAGER = 11;
1188         /**
1189          * This network is disabled due to user switching
1190          */
1191         public static final int DISABLED_DUE_TO_USER_SWITCH = 12;
1192         /**
1193          * This network is disabled due to wrong password
1194          */
1195         public static final int DISABLED_BY_WRONG_PASSWORD = 13;
1196         /**
1197          * This network is disabled because service is not subscribed
1198          */
1199         public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 14;
1200         /**
1201          * This Maximum disable reason value
1202          */
1203         public static final int NETWORK_SELECTION_DISABLED_MAX = 15;
1204 
1205         /**
1206          * Quality network selection disable reason String (for debug purpose)
1207          */
1208         public static final String[] QUALITY_NETWORK_SELECTION_DISABLE_REASON = {
1209                 "NETWORK_SELECTION_ENABLE",
1210                 "NETWORK_SELECTION_DISABLED_BAD_LINK", // deprecated
1211                 "NETWORK_SELECTION_DISABLED_ASSOCIATION_REJECTION ",
1212                 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE",
1213                 "NETWORK_SELECTION_DISABLED_DHCP_FAILURE",
1214                 "NETWORK_SELECTION_DISABLED_DNS_FAILURE",
1215                 "NETWORK_SELECTION_DISABLED_NO_INTERNET_TEMPORARY",
1216                 "NETWORK_SELECTION_DISABLED_WPS_START",
1217                 "NETWORK_SELECTION_DISABLED_TLS_VERSION",
1218                 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS",
1219                 "NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT",
1220                 "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER",
1221                 "NETWORK_SELECTION_DISABLED_BY_USER_SWITCH",
1222                 "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD",
1223                 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_SUBSCRIPTION"
1224         };
1225 
1226         /**
1227          * Invalid time stamp for network selection disable
1228          */
1229         public static final long INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP = -1L;
1230 
1231         /**
1232          *  This constant indicates the current configuration has connect choice set
1233          */
1234         private static final int CONNECT_CHOICE_EXISTS = 1;
1235 
1236         /**
1237          *  This constant indicates the current configuration does not have connect choice set
1238          */
1239         private static final int CONNECT_CHOICE_NOT_EXISTS = -1;
1240 
1241         // fields for QualityNetwork Selection
1242         /**
1243          * Network selection status, should be in one of three status: enable, temporaily disabled
1244          * or permanently disabled
1245          */
1246         private int mStatus;
1247 
1248         /**
1249          * Reason for disable this network
1250          */
1251         private int mNetworkSelectionDisableReason;
1252 
1253         /**
1254          * Last time we temporarily disabled the configuration
1255          */
1256         private long mTemporarilyDisabledTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;
1257 
1258         /**
1259          * counter for each Network selection disable reason
1260          */
1261         private int[] mNetworkSeclectionDisableCounter = new int[NETWORK_SELECTION_DISABLED_MAX];
1262 
1263         /**
1264          * Connect Choice over this configuration
1265          *
1266          * When current wifi configuration is visible to the user but user explicitly choose to
1267          * connect to another network X, the another networks X's configure key will be stored here.
1268          * We will consider user has a preference of X over this network. And in the future,
1269          * network selection will always give X a higher preference over this configuration.
1270          * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP
1271          */
1272         private String mConnectChoice;
1273 
1274         /**
1275          * The system timestamp when we records the connectChoice. This value is obtained from
1276          * System.currentTimeMillis
1277          */
1278         private long mConnectChoiceTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;
1279 
1280         /**
1281          * Used to cache the temporary candidate during the network selection procedure. It will be
1282          * kept updating once a new scan result has a higher score than current one
1283          */
1284         private ScanResult mCandidate;
1285 
1286         /**
1287          * Used to cache the score of the current temporary candidate during the network
1288          * selection procedure.
1289          */
1290         private int mCandidateScore;
1291 
1292         /**
1293          * Indicate whether this network is visible in latest Qualified Network Selection. This
1294          * means there is scan result found related to this Configuration and meet the minimum
1295          * requirement. The saved network need not join latest Qualified Network Selection. For
1296          * example, it is disabled. True means network is visible in latest Qualified Network
1297          * Selection and false means network is invisible
1298          */
1299         private boolean mSeenInLastQualifiedNetworkSelection;
1300 
1301         /**
1302          * Boolean indicating if we have ever successfully connected to this network.
1303          *
1304          * This value will be set to true upon a successful connection.
1305          * This value will be set to false if a previous value was not stored in the config or if
1306          * the credentials are updated (ex. a password change).
1307          */
1308         private boolean mHasEverConnected;
1309 
1310         /**
1311          * Boolean indicating whether {@link com.android.server.wifi.RecommendedNetworkEvaluator}
1312          * chose not to connect to this network in the last qualified network selection process.
1313          */
1314         private boolean mNotRecommended;
1315 
1316         /**
1317          * Set whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} does not
1318          * recommend connecting to this network.
1319          */
setNotRecommended(boolean notRecommended)1320         public void setNotRecommended(boolean notRecommended) {
1321             mNotRecommended = notRecommended;
1322         }
1323 
1324         /**
1325          * Returns whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} does not
1326          * recommend connecting to this network.
1327          */
isNotRecommended()1328         public boolean isNotRecommended() {
1329             return mNotRecommended;
1330         }
1331 
1332         /**
1333          * set whether this network is visible in latest Qualified Network Selection
1334          * @param seen value set to candidate
1335          */
setSeenInLastQualifiedNetworkSelection(boolean seen)1336         public void setSeenInLastQualifiedNetworkSelection(boolean seen) {
1337             mSeenInLastQualifiedNetworkSelection =  seen;
1338         }
1339 
1340         /**
1341          * get whether this network is visible in latest Qualified Network Selection
1342          * @return returns true -- network is visible in latest Qualified Network Selection
1343          *         false -- network is invisible in latest Qualified Network Selection
1344          */
getSeenInLastQualifiedNetworkSelection()1345         public boolean getSeenInLastQualifiedNetworkSelection() {
1346             return mSeenInLastQualifiedNetworkSelection;
1347         }
1348         /**
1349          * set the temporary candidate of current network selection procedure
1350          * @param scanCandidate {@link ScanResult} the candidate set to mCandidate
1351          */
setCandidate(ScanResult scanCandidate)1352         public void setCandidate(ScanResult scanCandidate) {
1353             mCandidate = scanCandidate;
1354         }
1355 
1356         /**
1357          * get the temporary candidate of current network selection procedure
1358          * @return  returns {@link ScanResult} temporary candidate of current network selection
1359          * procedure
1360          */
getCandidate()1361         public ScanResult getCandidate() {
1362             return mCandidate;
1363         }
1364 
1365         /**
1366          * set the score of the temporary candidate of current network selection procedure
1367          * @param score value set to mCandidateScore
1368          */
setCandidateScore(int score)1369         public void setCandidateScore(int score) {
1370             mCandidateScore = score;
1371         }
1372 
1373         /**
1374          * get the score of the temporary candidate of current network selection procedure
1375          * @return returns score of the temporary candidate of current network selection procedure
1376          */
getCandidateScore()1377         public int getCandidateScore() {
1378             return mCandidateScore;
1379         }
1380 
1381         /**
1382          * get user preferred choice over this configuration
1383          *@return returns configKey of user preferred choice over this configuration
1384          */
getConnectChoice()1385         public String getConnectChoice() {
1386             return mConnectChoice;
1387         }
1388 
1389         /**
1390          * set user preferred choice over this configuration
1391          * @param newConnectChoice, the configKey of user preferred choice over this configuration
1392          */
setConnectChoice(String newConnectChoice)1393         public void setConnectChoice(String newConnectChoice) {
1394             mConnectChoice = newConnectChoice;
1395         }
1396 
1397         /**
1398          * get the timeStamp when user select a choice over this configuration
1399          * @return returns when current connectChoice is set (time from System.currentTimeMillis)
1400          */
getConnectChoiceTimestamp()1401         public long getConnectChoiceTimestamp() {
1402             return mConnectChoiceTimestamp;
1403         }
1404 
1405         /**
1406          * set the timeStamp when user select a choice over this configuration
1407          * @param timeStamp, the timestamp set to connectChoiceTimestamp, expected timestamp should
1408          *        be obtained from System.currentTimeMillis
1409          */
setConnectChoiceTimestamp(long timeStamp)1410         public void setConnectChoiceTimestamp(long timeStamp) {
1411             mConnectChoiceTimestamp = timeStamp;
1412         }
1413 
1414         /**
1415          * get current Quality network selection status
1416          * @return returns current Quality network selection status in String (for debug purpose)
1417          */
getNetworkStatusString()1418         public String getNetworkStatusString() {
1419             return QUALITY_NETWORK_SELECTION_STATUS[mStatus];
1420         }
1421 
setHasEverConnected(boolean value)1422         public void setHasEverConnected(boolean value) {
1423             mHasEverConnected = value;
1424         }
1425 
getHasEverConnected()1426         public boolean getHasEverConnected() {
1427             return mHasEverConnected;
1428         }
1429 
NetworkSelectionStatus()1430         public NetworkSelectionStatus() {
1431             // previously stored configs will not have this parameter, so we default to false.
1432             mHasEverConnected = false;
1433         };
1434 
1435         /**
1436          * @param reason specific error reason
1437          * @return  corresponding network disable reason String (for debug purpose)
1438          */
getNetworkDisableReasonString(int reason)1439         public static String getNetworkDisableReasonString(int reason) {
1440             if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) {
1441                 return QUALITY_NETWORK_SELECTION_DISABLE_REASON[reason];
1442             } else {
1443                 return null;
1444             }
1445         }
1446         /**
1447          * get current network disable reason
1448          * @return current network disable reason in String (for debug purpose)
1449          */
getNetworkDisableReasonString()1450         public String getNetworkDisableReasonString() {
1451             return QUALITY_NETWORK_SELECTION_DISABLE_REASON[mNetworkSelectionDisableReason];
1452         }
1453 
1454         /**
1455          * get current network network selection status
1456          * @return return current network network selection status
1457          */
getNetworkSelectionStatus()1458         public int getNetworkSelectionStatus() {
1459             return mStatus;
1460         }
1461         /**
1462          * @return whether current network is enabled to join network selection
1463          */
isNetworkEnabled()1464         public boolean isNetworkEnabled() {
1465             return mStatus == NETWORK_SELECTION_ENABLED;
1466         }
1467 
1468         /**
1469          * @return whether current network is temporary disabled
1470          */
isNetworkTemporaryDisabled()1471         public boolean isNetworkTemporaryDisabled() {
1472             return mStatus == NETWORK_SELECTION_TEMPORARY_DISABLED;
1473         }
1474 
1475         /**
1476          * @return returns whether current network is permanently disabled
1477          */
isNetworkPermanentlyDisabled()1478         public boolean isNetworkPermanentlyDisabled() {
1479             return mStatus == NETWORK_SELECTION_PERMANENTLY_DISABLED;
1480         }
1481 
1482         /**
1483          * set current networ work selection status
1484          * @param status network selection status to set
1485          */
setNetworkSelectionStatus(int status)1486         public void setNetworkSelectionStatus(int status) {
1487             if (status >= 0 && status < NETWORK_SELECTION_STATUS_MAX) {
1488                 mStatus = status;
1489             }
1490         }
1491 
1492         /**
1493          * @return returns current network's disable reason
1494          */
getNetworkSelectionDisableReason()1495         public int getNetworkSelectionDisableReason() {
1496             return mNetworkSelectionDisableReason;
1497         }
1498 
1499         /**
1500          * set Network disable reason
1501          * @param  reason Network disable reason
1502          */
setNetworkSelectionDisableReason(int reason)1503         public void setNetworkSelectionDisableReason(int reason) {
1504             if (reason >= 0 && reason < NETWORK_SELECTION_DISABLED_MAX) {
1505                 mNetworkSelectionDisableReason = reason;
1506             } else {
1507                 throw new IllegalArgumentException("Illegal reason value: " + reason);
1508             }
1509         }
1510 
1511         /**
1512          * check whether network is disabled by this reason
1513          * @param reason a specific disable reason
1514          * @return true -- network is disabled for this reason
1515          *         false -- network is not disabled for this reason
1516          */
isDisabledByReason(int reason)1517         public boolean isDisabledByReason(int reason) {
1518             return mNetworkSelectionDisableReason == reason;
1519         }
1520 
1521         /**
1522          * @param timeStamp Set when current network is disabled in millisecond since January 1,
1523          * 1970 00:00:00.0 UTC
1524          */
setDisableTime(long timeStamp)1525         public void setDisableTime(long timeStamp) {
1526             mTemporarilyDisabledTimestamp = timeStamp;
1527         }
1528 
1529         /**
1530          * @return returns when current network is disabled in millisecond since January 1,
1531          * 1970 00:00:00.0 UTC
1532          */
getDisableTime()1533         public long getDisableTime() {
1534             return mTemporarilyDisabledTimestamp;
1535         }
1536 
1537         /**
1538          * get the disable counter of a specific reason
1539          * @param  reason specific failure reason
1540          * @exception throw IllegalArgumentException for illegal input
1541          * @return counter number for specific error reason.
1542          */
getDisableReasonCounter(int reason)1543         public int getDisableReasonCounter(int reason) {
1544             if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) {
1545                 return mNetworkSeclectionDisableCounter[reason];
1546             } else {
1547                 throw new IllegalArgumentException("Illegal reason value: " + reason);
1548             }
1549         }
1550 
1551         /**
1552          * set the counter of a specific failure reason
1553          * @param reason reason for disable error
1554          * @param value the counter value for this specific reason
1555          * @exception throw IllegalArgumentException for illegal input
1556          */
setDisableReasonCounter(int reason, int value)1557         public void setDisableReasonCounter(int reason, int value) {
1558             if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) {
1559                 mNetworkSeclectionDisableCounter[reason] = value;
1560             } else {
1561                 throw new IllegalArgumentException("Illegal reason value: " + reason);
1562             }
1563         }
1564 
1565         /**
1566          * increment the counter of a specific failure reason
1567          * @param reason a specific failure reason
1568          * @exception throw IllegalArgumentException for illegal input
1569          */
incrementDisableReasonCounter(int reason)1570         public void incrementDisableReasonCounter(int reason) {
1571             if (reason >= NETWORK_SELECTION_ENABLE  && reason < NETWORK_SELECTION_DISABLED_MAX) {
1572                 mNetworkSeclectionDisableCounter[reason]++;
1573             } else {
1574                 throw new IllegalArgumentException("Illegal reason value: " + reason);
1575             }
1576         }
1577 
1578         /**
1579          * clear the counter of a specific failure reason
1580          * @hide
1581          * @param reason a specific failure reason
1582          * @exception throw IllegalArgumentException for illegal input
1583          */
clearDisableReasonCounter(int reason)1584         public void clearDisableReasonCounter(int reason) {
1585             if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) {
1586                 mNetworkSeclectionDisableCounter[reason] = NETWORK_SELECTION_ENABLE;
1587             } else {
1588                 throw new IllegalArgumentException("Illegal reason value: " + reason);
1589             }
1590         }
1591 
1592         /**
1593          * clear all the failure reason counters
1594          */
clearDisableReasonCounter()1595         public void clearDisableReasonCounter() {
1596             Arrays.fill(mNetworkSeclectionDisableCounter, NETWORK_SELECTION_ENABLE);
1597         }
1598 
1599         /**
1600          * BSSID for connection to this network (through network selection procedure)
1601          */
1602         private String mNetworkSelectionBSSID;
1603 
1604         /**
1605          * get current network Selection BSSID
1606          * @return current network Selection BSSID
1607          */
getNetworkSelectionBSSID()1608         public String getNetworkSelectionBSSID() {
1609             return mNetworkSelectionBSSID;
1610         }
1611 
1612         /**
1613          * set network Selection BSSID
1614          * @param bssid The target BSSID for assocaition
1615          */
setNetworkSelectionBSSID(String bssid)1616         public void setNetworkSelectionBSSID(String bssid) {
1617             mNetworkSelectionBSSID = bssid;
1618         }
1619 
copy(NetworkSelectionStatus source)1620         public void copy(NetworkSelectionStatus source) {
1621             mStatus = source.mStatus;
1622             mNetworkSelectionDisableReason = source.mNetworkSelectionDisableReason;
1623             for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX;
1624                     index++) {
1625                 mNetworkSeclectionDisableCounter[index] =
1626                         source.mNetworkSeclectionDisableCounter[index];
1627             }
1628             mTemporarilyDisabledTimestamp = source.mTemporarilyDisabledTimestamp;
1629             mNetworkSelectionBSSID = source.mNetworkSelectionBSSID;
1630             setSeenInLastQualifiedNetworkSelection(source.getSeenInLastQualifiedNetworkSelection());
1631             setCandidate(source.getCandidate());
1632             setCandidateScore(source.getCandidateScore());
1633             setConnectChoice(source.getConnectChoice());
1634             setConnectChoiceTimestamp(source.getConnectChoiceTimestamp());
1635             setHasEverConnected(source.getHasEverConnected());
1636             setNotRecommended(source.isNotRecommended());
1637         }
1638 
writeToParcel(Parcel dest)1639         public void writeToParcel(Parcel dest) {
1640             dest.writeInt(getNetworkSelectionStatus());
1641             dest.writeInt(getNetworkSelectionDisableReason());
1642             for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX;
1643                     index++) {
1644                 dest.writeInt(getDisableReasonCounter(index));
1645             }
1646             dest.writeLong(getDisableTime());
1647             dest.writeString(getNetworkSelectionBSSID());
1648             if (getConnectChoice() != null) {
1649                 dest.writeInt(CONNECT_CHOICE_EXISTS);
1650                 dest.writeString(getConnectChoice());
1651                 dest.writeLong(getConnectChoiceTimestamp());
1652             } else {
1653                 dest.writeInt(CONNECT_CHOICE_NOT_EXISTS);
1654             }
1655             dest.writeInt(getHasEverConnected() ? 1 : 0);
1656             dest.writeInt(isNotRecommended() ? 1 : 0);
1657         }
1658 
readFromParcel(Parcel in)1659         public void readFromParcel(Parcel in) {
1660             setNetworkSelectionStatus(in.readInt());
1661             setNetworkSelectionDisableReason(in.readInt());
1662             for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX;
1663                     index++) {
1664                 setDisableReasonCounter(index, in.readInt());
1665             }
1666             setDisableTime(in.readLong());
1667             setNetworkSelectionBSSID(in.readString());
1668             if (in.readInt() == CONNECT_CHOICE_EXISTS) {
1669                 setConnectChoice(in.readString());
1670                 setConnectChoiceTimestamp(in.readLong());
1671             } else {
1672                 setConnectChoice(null);
1673                 setConnectChoiceTimestamp(INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
1674             }
1675             setHasEverConnected(in.readInt() != 0);
1676             setNotRecommended(in.readInt() != 0);
1677         }
1678     }
1679 
1680     /**
1681      * @hide
1682      * network selection related member
1683      */
1684     private NetworkSelectionStatus mNetworkSelectionStatus = new NetworkSelectionStatus();
1685 
1686     /**
1687      * @hide
1688      * This class is intended to store extra failure reason information for the most recent
1689      * connection attempt, so that it may be surfaced to the settings UI
1690      */
1691     public static class RecentFailure {
1692 
1693         /**
1694          * No recent failure, or no specific reason given for the recent connection failure
1695          */
1696         public static final int NONE = 0;
1697         /**
1698          * Connection to this network recently failed due to Association Rejection Status 17
1699          * (AP is full)
1700          */
1701         public static final int STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17;
1702         /**
1703          * Association Rejection Status code (NONE for success/non-association-rejection-fail)
1704          */
1705         private int mAssociationStatus = NONE;
1706 
1707         /**
1708          * @param status the association status code for the recent failure
1709          */
setAssociationStatus(int status)1710         public void setAssociationStatus(int status) {
1711             mAssociationStatus = status;
1712         }
1713         /**
1714          * Sets the RecentFailure to NONE
1715          */
clear()1716         public void clear() {
1717             mAssociationStatus = NONE;
1718         }
1719         /**
1720          * Get the recent failure code
1721          */
getAssociationStatus()1722         public int getAssociationStatus() {
1723             return mAssociationStatus;
1724         }
1725     }
1726 
1727     /**
1728      * @hide
1729      * RecentFailure member
1730      */
1731     final public RecentFailure recentFailure = new RecentFailure();
1732 
1733     /**
1734      * @hide
1735      * @return network selection status
1736      */
getNetworkSelectionStatus()1737     public NetworkSelectionStatus getNetworkSelectionStatus() {
1738         return mNetworkSelectionStatus;
1739     }
1740 
1741     /**
1742      * Set the network selection status
1743      * @hide
1744      */
setNetworkSelectionStatus(NetworkSelectionStatus status)1745     public void setNetworkSelectionStatus(NetworkSelectionStatus status) {
1746         mNetworkSelectionStatus = status;
1747     }
1748 
1749     /**
1750      * @hide
1751      * Linked Configurations: represent the set of Wificonfigurations that are equivalent
1752      * regarding roaming and auto-joining.
1753      * The linked configuration may or may not have same SSID, and may or may not have same
1754      * credentials.
1755      * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server.
1756      */
1757     public HashMap<String, Integer>  linkedConfigurations;
1758 
WifiConfiguration()1759     public WifiConfiguration() {
1760         networkId = INVALID_NETWORK_ID;
1761         SSID = null;
1762         BSSID = null;
1763         FQDN = null;
1764         roamingConsortiumIds = new long[0];
1765         priority = 0;
1766         hiddenSSID = false;
1767         allowedKeyManagement = new BitSet();
1768         allowedProtocols = new BitSet();
1769         allowedAuthAlgorithms = new BitSet();
1770         allowedPairwiseCiphers = new BitSet();
1771         allowedGroupCiphers = new BitSet();
1772         allowedGroupManagementCiphers = new BitSet();
1773         allowedSuiteBCiphers = new BitSet();
1774         wepKeys = new String[4];
1775         for (int i = 0; i < wepKeys.length; i++) {
1776             wepKeys[i] = null;
1777         }
1778         enterpriseConfig = new WifiEnterpriseConfig();
1779         selfAdded = false;
1780         didSelfAdd = false;
1781         ephemeral = false;
1782         osu = false;
1783         trusted = true; // Networks are considered trusted by default.
1784         fromWifiNetworkSuggestion = false;
1785         fromWifiNetworkSpecifier = false;
1786         meteredHint = false;
1787         meteredOverride = METERED_OVERRIDE_NONE;
1788         useExternalScores = false;
1789         validatedInternetAccess = false;
1790         mIpConfiguration = new IpConfiguration();
1791         lastUpdateUid = -1;
1792         creatorUid = -1;
1793         shared = true;
1794         dtimInterval = 0;
1795         mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS);
1796     }
1797 
1798     /**
1799      * Identify if this configuration represents a Passpoint network
1800      */
isPasspoint()1801     public boolean isPasspoint() {
1802         return !TextUtils.isEmpty(FQDN)
1803                 && !TextUtils.isEmpty(providerFriendlyName)
1804                 && enterpriseConfig != null
1805                 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
1806     }
1807 
1808     /**
1809      * Helper function, identify if a configuration is linked
1810      * @hide
1811      */
isLinked(WifiConfiguration config)1812     public boolean isLinked(WifiConfiguration config) {
1813         if (config != null) {
1814             if (config.linkedConfigurations != null && linkedConfigurations != null) {
1815                 if (config.linkedConfigurations.get(configKey()) != null
1816                         && linkedConfigurations.get(config.configKey()) != null) {
1817                     return true;
1818                 }
1819             }
1820         }
1821         return  false;
1822     }
1823 
1824     /**
1825      * Helper function, idenfity if a configuration should be treated as an enterprise network
1826      * @hide
1827      */
1828     @UnsupportedAppUsage
isEnterprise()1829     public boolean isEnterprise() {
1830         return (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
1831                 || allowedKeyManagement.get(KeyMgmt.IEEE8021X)
1832                 || allowedKeyManagement.get(KeyMgmt.SUITE_B_192))
1833                 && enterpriseConfig != null
1834                 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
1835     }
1836 
1837     @Override
toString()1838     public String toString() {
1839         StringBuilder sbuf = new StringBuilder();
1840         if (this.status == WifiConfiguration.Status.CURRENT) {
1841             sbuf.append("* ");
1842         } else if (this.status == WifiConfiguration.Status.DISABLED) {
1843             sbuf.append("- DSBLE ");
1844         }
1845         sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
1846                 append(" PROVIDER-NAME: ").append(this.providerFriendlyName).
1847                 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN)
1848                 .append(" PRIO: ").append(this.priority)
1849                 .append(" HIDDEN: ").append(this.hiddenSSID)
1850                 .append(" PMF: ").append(this.requirePMF)
1851                 .append('\n');
1852 
1853 
1854         sbuf.append(" NetworkSelectionStatus ")
1855                 .append(mNetworkSelectionStatus.getNetworkStatusString() + "\n");
1856         if (mNetworkSelectionStatus.getNetworkSelectionDisableReason() > 0) {
1857             sbuf.append(" mNetworkSelectionDisableReason ")
1858                     .append(mNetworkSelectionStatus.getNetworkDisableReasonString() + "\n");
1859 
1860             for (int index = mNetworkSelectionStatus.NETWORK_SELECTION_ENABLE;
1861                     index < mNetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX; index++) {
1862                 if (mNetworkSelectionStatus.getDisableReasonCounter(index) != 0) {
1863                     sbuf.append(NetworkSelectionStatus.getNetworkDisableReasonString(index)
1864                             + " counter:" + mNetworkSelectionStatus.getDisableReasonCounter(index)
1865                             + "\n");
1866                 }
1867             }
1868         }
1869         if (mNetworkSelectionStatus.getConnectChoice() != null) {
1870             sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice());
1871             sbuf.append(" connect choice set time: ")
1872                     .append(TimeUtils.logTimeOfDay(
1873                             mNetworkSelectionStatus.getConnectChoiceTimestamp()));
1874         }
1875         sbuf.append(" hasEverConnected: ")
1876                 .append(mNetworkSelectionStatus.getHasEverConnected()).append("\n");
1877 
1878         if (this.numAssociation > 0) {
1879             sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
1880         }
1881         if (this.numNoInternetAccessReports > 0) {
1882             sbuf.append(" numNoInternetAccessReports ");
1883             sbuf.append(this.numNoInternetAccessReports).append("\n");
1884         }
1885         if (this.updateTime != null) {
1886             sbuf.append(" update ").append(this.updateTime).append("\n");
1887         }
1888         if (this.creationTime != null) {
1889             sbuf.append(" creation ").append(this.creationTime).append("\n");
1890         }
1891         if (this.didSelfAdd) sbuf.append(" didSelfAdd");
1892         if (this.selfAdded) sbuf.append(" selfAdded");
1893         if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess");
1894         if (this.ephemeral) sbuf.append(" ephemeral");
1895         if (this.osu) sbuf.append(" osu");
1896         if (this.trusted) sbuf.append(" trusted");
1897         if (this.fromWifiNetworkSuggestion) sbuf.append(" fromWifiNetworkSuggestion");
1898         if (this.fromWifiNetworkSpecifier) sbuf.append(" fromWifiNetworkSpecifier");
1899         if (this.meteredHint) sbuf.append(" meteredHint");
1900         if (this.useExternalScores) sbuf.append(" useExternalScores");
1901         if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess
1902                 || this.ephemeral || this.trusted || this.fromWifiNetworkSuggestion
1903                 || this.fromWifiNetworkSpecifier || this.meteredHint || this.useExternalScores) {
1904             sbuf.append("\n");
1905         }
1906         if (this.meteredOverride != METERED_OVERRIDE_NONE) {
1907             sbuf.append(" meteredOverride ").append(meteredOverride).append("\n");
1908         }
1909         sbuf.append(" macRandomizationSetting: ").append(macRandomizationSetting).append("\n");
1910         sbuf.append(" mRandomizedMacAddress: ").append(mRandomizedMacAddress).append("\n");
1911         sbuf.append(" KeyMgmt:");
1912         for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
1913             if (this.allowedKeyManagement.get(k)) {
1914                 sbuf.append(" ");
1915                 if (k < KeyMgmt.strings.length) {
1916                     sbuf.append(KeyMgmt.strings[k]);
1917                 } else {
1918                     sbuf.append("??");
1919                 }
1920             }
1921         }
1922         sbuf.append(" Protocols:");
1923         for (int p = 0; p < this.allowedProtocols.size(); p++) {
1924             if (this.allowedProtocols.get(p)) {
1925                 sbuf.append(" ");
1926                 if (p < Protocol.strings.length) {
1927                     sbuf.append(Protocol.strings[p]);
1928                 } else {
1929                     sbuf.append("??");
1930                 }
1931             }
1932         }
1933         sbuf.append('\n');
1934         sbuf.append(" AuthAlgorithms:");
1935         for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) {
1936             if (this.allowedAuthAlgorithms.get(a)) {
1937                 sbuf.append(" ");
1938                 if (a < AuthAlgorithm.strings.length) {
1939                     sbuf.append(AuthAlgorithm.strings[a]);
1940                 } else {
1941                     sbuf.append("??");
1942                 }
1943             }
1944         }
1945         sbuf.append('\n');
1946         sbuf.append(" PairwiseCiphers:");
1947         for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) {
1948             if (this.allowedPairwiseCiphers.get(pc)) {
1949                 sbuf.append(" ");
1950                 if (pc < PairwiseCipher.strings.length) {
1951                     sbuf.append(PairwiseCipher.strings[pc]);
1952                 } else {
1953                     sbuf.append("??");
1954                 }
1955             }
1956         }
1957         sbuf.append('\n');
1958         sbuf.append(" GroupCiphers:");
1959         for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) {
1960             if (this.allowedGroupCiphers.get(gc)) {
1961                 sbuf.append(" ");
1962                 if (gc < GroupCipher.strings.length) {
1963                     sbuf.append(GroupCipher.strings[gc]);
1964                 } else {
1965                     sbuf.append("??");
1966                 }
1967             }
1968         }
1969         sbuf.append('\n');
1970         sbuf.append(" GroupMgmtCiphers:");
1971         for (int gmc = 0; gmc < this.allowedGroupManagementCiphers.size(); gmc++) {
1972             if (this.allowedGroupManagementCiphers.get(gmc)) {
1973                 sbuf.append(" ");
1974                 if (gmc < GroupMgmtCipher.strings.length) {
1975                     sbuf.append(GroupMgmtCipher.strings[gmc]);
1976                 } else {
1977                     sbuf.append("??");
1978                 }
1979             }
1980         }
1981         sbuf.append('\n');
1982         sbuf.append(" SuiteBCiphers:");
1983         for (int sbc = 0; sbc < this.allowedSuiteBCiphers.size(); sbc++) {
1984             if (this.allowedSuiteBCiphers.get(sbc)) {
1985                 sbuf.append(" ");
1986                 if (sbc < SuiteBCipher.strings.length) {
1987                     sbuf.append(SuiteBCipher.strings[sbc]);
1988                 } else {
1989                     sbuf.append("??");
1990                 }
1991             }
1992         }
1993         sbuf.append('\n').append(" PSK/SAE: ");
1994         if (this.preSharedKey != null) {
1995             sbuf.append('*');
1996         }
1997 
1998         sbuf.append("\nEnterprise config:\n");
1999         sbuf.append(enterpriseConfig);
2000 
2001         sbuf.append("IP config:\n");
2002         sbuf.append(mIpConfiguration.toString());
2003 
2004         if (mNetworkSelectionStatus.getNetworkSelectionBSSID() != null) {
2005             sbuf.append(" networkSelectionBSSID="
2006                     + mNetworkSelectionStatus.getNetworkSelectionBSSID());
2007         }
2008         long now_ms = SystemClock.elapsedRealtime();
2009         if (mNetworkSelectionStatus.getDisableTime() != NetworkSelectionStatus
2010                 .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP) {
2011             sbuf.append('\n');
2012             long diff = now_ms - mNetworkSelectionStatus.getDisableTime();
2013             if (diff <= 0) {
2014                 sbuf.append(" blackListed since <incorrect>");
2015             } else {
2016                 sbuf.append(" blackListed: ").append(Long.toString(diff / 1000)).append("sec ");
2017             }
2018         }
2019         if (creatorUid != 0) sbuf.append(" cuid=" + creatorUid);
2020         if (creatorName != null) sbuf.append(" cname=" + creatorName);
2021         if (lastUpdateUid != 0) sbuf.append(" luid=" + lastUpdateUid);
2022         if (lastUpdateName != null) sbuf.append(" lname=" + lastUpdateName);
2023         if (updateIdentifier != null) sbuf.append(" updateIdentifier=" + updateIdentifier);
2024         sbuf.append(" lcuid=" + lastConnectUid);
2025         sbuf.append(" userApproved=" + userApprovedAsString(userApproved));
2026         sbuf.append(" noInternetAccessExpected=" + noInternetAccessExpected);
2027         sbuf.append(" ");
2028 
2029         if (this.lastConnected != 0) {
2030             sbuf.append('\n');
2031             sbuf.append("lastConnected: ").append(TimeUtils.logTimeOfDay(this.lastConnected));
2032             sbuf.append(" ");
2033         }
2034         sbuf.append('\n');
2035         if (this.linkedConfigurations != null) {
2036             for (String key : this.linkedConfigurations.keySet()) {
2037                 sbuf.append(" linked: ").append(key);
2038                 sbuf.append('\n');
2039             }
2040         }
2041         sbuf.append("recentFailure: ").append("Association Rejection code: ")
2042                 .append(recentFailure.getAssociationStatus()).append("\n");
2043         return sbuf.toString();
2044     }
2045 
2046     /** {@hide} */
2047     @UnsupportedAppUsage
getPrintableSsid()2048     public String getPrintableSsid() {
2049         if (SSID == null) return "";
2050         final int length = SSID.length();
2051         if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') {
2052             return SSID.substring(1, length - 1);
2053         }
2054 
2055         /** The ascii-encoded string format is P"<ascii-encoded-string>"
2056          * The decoding is implemented in the supplicant for a newly configured
2057          * network.
2058          */
2059         if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') &&
2060                 (SSID.charAt(length-1) == '"')) {
2061             WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(
2062                     SSID.substring(2, length - 1));
2063             return wifiSsid.toString();
2064         }
2065         return SSID;
2066     }
2067 
2068     /** @hide **/
userApprovedAsString(int userApproved)2069     public static String userApprovedAsString(int userApproved) {
2070         switch (userApproved) {
2071             case USER_APPROVED:
2072                 return "USER_APPROVED";
2073             case USER_BANNED:
2074                 return "USER_BANNED";
2075             case USER_UNSPECIFIED:
2076                 return "USER_UNSPECIFIED";
2077             default:
2078                 return "INVALID";
2079         }
2080     }
2081 
2082     /**
2083      * Get an identifier for associating credentials with this config
2084      * @param current configuration contains values for additional fields
2085      *                that are not part of this configuration. Used
2086      *                when a config with some fields is passed by an application.
2087      * @throws IllegalStateException if config is invalid for key id generation
2088      * @hide
2089      */
getKeyIdForCredentials(WifiConfiguration current)2090     public String getKeyIdForCredentials(WifiConfiguration current) {
2091         String keyMgmt = "";
2092 
2093         try {
2094             // Get current config details for fields that are not initialized
2095             if (TextUtils.isEmpty(SSID)) SSID = current.SSID;
2096             if (allowedKeyManagement.cardinality() == 0) {
2097                 allowedKeyManagement = current.allowedKeyManagement;
2098             }
2099             if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
2100                 keyMgmt += KeyMgmt.strings[KeyMgmt.WPA_EAP];
2101             }
2102             if (allowedKeyManagement.get(KeyMgmt.OSEN)) {
2103                 keyMgmt += KeyMgmt.strings[KeyMgmt.OSEN];
2104             }
2105             if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
2106                 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X];
2107             }
2108             if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
2109                 keyMgmt += KeyMgmt.strings[KeyMgmt.SUITE_B_192];
2110             }
2111 
2112             if (TextUtils.isEmpty(keyMgmt)) {
2113                 throw new IllegalStateException("Not an EAP network");
2114             }
2115 
2116             String keyId = trimStringForKeyId(SSID) + "_" + keyMgmt + "_"
2117                     + trimStringForKeyId(enterpriseConfig.getKeyId(current != null
2118                     ? current.enterpriseConfig : null));
2119 
2120             if (!fromWifiNetworkSuggestion) {
2121                 return keyId;
2122             }
2123             return keyId + "_" + trimStringForKeyId(BSSID) + "_" + trimStringForKeyId(creatorName);
2124         } catch (NullPointerException e) {
2125             throw new IllegalStateException("Invalid config details");
2126         }
2127     }
2128 
trimStringForKeyId(String string)2129     private String trimStringForKeyId(String string) {
2130         if (string == null) {
2131             return "";
2132         }
2133         // Remove quotes and spaces
2134         return string.replace("\"", "").replace(" ", "");
2135     }
2136 
readBitSet(Parcel src)2137     private static BitSet readBitSet(Parcel src) {
2138         int cardinality = src.readInt();
2139 
2140         BitSet set = new BitSet();
2141         for (int i = 0; i < cardinality; i++) {
2142             set.set(src.readInt());
2143         }
2144 
2145         return set;
2146     }
2147 
writeBitSet(Parcel dest, BitSet set)2148     private static void writeBitSet(Parcel dest, BitSet set) {
2149         int nextSetBit = -1;
2150 
2151         dest.writeInt(set.cardinality());
2152 
2153         while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
2154             dest.writeInt(nextSetBit);
2155         }
2156     }
2157 
2158     /** @hide */
2159     @UnsupportedAppUsage
getAuthType()2160     public int getAuthType() {
2161         if (allowedKeyManagement.cardinality() > 1) {
2162             throw new IllegalStateException("More than one auth type set");
2163         }
2164         if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
2165             return KeyMgmt.WPA_PSK;
2166         } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
2167             return KeyMgmt.WPA2_PSK;
2168         } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
2169             return KeyMgmt.WPA_EAP;
2170         } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
2171             return KeyMgmt.IEEE8021X;
2172         } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
2173             return KeyMgmt.SAE;
2174         } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
2175             return KeyMgmt.OWE;
2176         } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
2177             return KeyMgmt.SUITE_B_192;
2178         }
2179         return KeyMgmt.NONE;
2180     }
2181 
2182     /* @hide
2183      * Cache the config key, this seems useful as a speed up since a lot of
2184      * lookups in the config store are done and based on this key.
2185      */
2186     String mCachedConfigKey;
2187 
2188     /** @hide
2189      *  return the string used to calculate the hash in WifiConfigStore
2190      *  and uniquely identify this WifiConfiguration
2191      */
configKey(boolean allowCached)2192     public String configKey(boolean allowCached) {
2193         String key;
2194         if (allowCached && mCachedConfigKey != null) {
2195             key = mCachedConfigKey;
2196         } else if (providerFriendlyName != null) {
2197             key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP];
2198             if (!shared) {
2199                 key += "-" + Integer.toString(UserHandle.getUserId(creatorUid));
2200             }
2201         } else {
2202             key = getSsidAndSecurityTypeString();
2203             if (!shared) {
2204                 key += "-" + Integer.toString(UserHandle.getUserId(creatorUid));
2205             }
2206             mCachedConfigKey = key;
2207         }
2208         return key;
2209     }
2210 
2211     /** @hide
2212      *  return the SSID + security type in String format.
2213      */
getSsidAndSecurityTypeString()2214     public String getSsidAndSecurityTypeString() {
2215         String key;
2216         if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
2217             key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK];
2218         } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
2219                 || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
2220             key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];
2221         } else if (wepKeys[0] != null) {
2222             key = SSID + "WEP";
2223         } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
2224             key = SSID + KeyMgmt.strings[KeyMgmt.OWE];
2225         } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
2226             key = SSID + KeyMgmt.strings[KeyMgmt.SAE];
2227         } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
2228             key = SSID + KeyMgmt.strings[KeyMgmt.SUITE_B_192];
2229         } else {
2230             key = SSID + KeyMgmt.strings[KeyMgmt.NONE];
2231         }
2232         return key;
2233     }
2234 
2235     /** @hide
2236      * get configKey, force calculating the config string
2237      */
configKey()2238     public String configKey() {
2239         return configKey(false);
2240     }
2241 
2242     /** @hide */
2243     @UnsupportedAppUsage
getIpConfiguration()2244     public IpConfiguration getIpConfiguration() {
2245         return mIpConfiguration;
2246     }
2247 
2248     /** @hide */
2249     @UnsupportedAppUsage
setIpConfiguration(IpConfiguration ipConfiguration)2250     public void setIpConfiguration(IpConfiguration ipConfiguration) {
2251         if (ipConfiguration == null) ipConfiguration = new IpConfiguration();
2252         mIpConfiguration = ipConfiguration;
2253     }
2254 
2255     /** @hide */
2256     @UnsupportedAppUsage
getStaticIpConfiguration()2257     public StaticIpConfiguration getStaticIpConfiguration() {
2258         return mIpConfiguration.getStaticIpConfiguration();
2259     }
2260 
2261     /** @hide */
2262     @UnsupportedAppUsage
setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration)2263     public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
2264         mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration);
2265     }
2266 
2267     /** @hide */
2268     @UnsupportedAppUsage
getIpAssignment()2269     public IpConfiguration.IpAssignment getIpAssignment() {
2270         return mIpConfiguration.ipAssignment;
2271     }
2272 
2273     /** @hide */
2274     @UnsupportedAppUsage
setIpAssignment(IpConfiguration.IpAssignment ipAssignment)2275     public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) {
2276         mIpConfiguration.ipAssignment = ipAssignment;
2277     }
2278 
2279     /** @hide */
2280     @UnsupportedAppUsage
getProxySettings()2281     public IpConfiguration.ProxySettings getProxySettings() {
2282         return mIpConfiguration.proxySettings;
2283     }
2284 
2285     /** @hide */
2286     @UnsupportedAppUsage
setProxySettings(IpConfiguration.ProxySettings proxySettings)2287     public void setProxySettings(IpConfiguration.ProxySettings proxySettings) {
2288         mIpConfiguration.proxySettings = proxySettings;
2289     }
2290 
2291     /**
2292      * Returns the HTTP proxy used by this object.
2293      * @return a {@link ProxyInfo httpProxy} representing the proxy specified by this
2294      *                  WifiConfiguration, or {@code null} if no proxy is specified.
2295      */
getHttpProxy()2296     public ProxyInfo getHttpProxy() {
2297         if (mIpConfiguration.proxySettings == IpConfiguration.ProxySettings.NONE) {
2298             return null;
2299         }
2300         return new ProxyInfo(mIpConfiguration.httpProxy);
2301     }
2302 
2303     /**
2304      * Set the {@link ProxyInfo} for this WifiConfiguration. This method should only be used by a
2305      * device owner or profile owner. When other apps attempt to save a {@link WifiConfiguration}
2306      * with modified proxy settings, the methods {@link WifiManager#addNetwork} and
2307      * {@link WifiManager#updateNetwork} fail and return {@code -1}.
2308      *
2309      * @param httpProxy {@link ProxyInfo} representing the httpProxy to be used by this
2310      *                  WifiConfiguration. Setting this to {@code null} will explicitly set no
2311      *                  proxy, removing any proxy that was previously set.
2312      * @exception IllegalArgumentException for invalid httpProxy
2313      */
setHttpProxy(ProxyInfo httpProxy)2314     public void setHttpProxy(ProxyInfo httpProxy) {
2315         if (httpProxy == null) {
2316             mIpConfiguration.setProxySettings(IpConfiguration.ProxySettings.NONE);
2317             mIpConfiguration.setHttpProxy(null);
2318             return;
2319         }
2320         ProxyInfo httpProxyCopy;
2321         ProxySettings proxySettingCopy;
2322         if (!Uri.EMPTY.equals(httpProxy.getPacFileUrl())) {
2323             proxySettingCopy = IpConfiguration.ProxySettings.PAC;
2324             // Construct a new PAC URL Proxy
2325             httpProxyCopy = new ProxyInfo(httpProxy.getPacFileUrl(), httpProxy.getPort());
2326         } else {
2327             proxySettingCopy = IpConfiguration.ProxySettings.STATIC;
2328             // Construct a new HTTP Proxy
2329             httpProxyCopy = new ProxyInfo(httpProxy.getHost(), httpProxy.getPort(),
2330                     httpProxy.getExclusionListAsString());
2331         }
2332         if (!httpProxyCopy.isValid()) {
2333             throw new IllegalArgumentException("Invalid ProxyInfo: " + httpProxyCopy.toString());
2334         }
2335         mIpConfiguration.setProxySettings(proxySettingCopy);
2336         mIpConfiguration.setHttpProxy(httpProxyCopy);
2337     }
2338 
2339     /** @hide */
2340     @UnsupportedAppUsage
setProxy(ProxySettings settings, ProxyInfo proxy)2341     public void setProxy(ProxySettings settings, ProxyInfo proxy) {
2342         mIpConfiguration.proxySettings = settings;
2343         mIpConfiguration.httpProxy = proxy;
2344     }
2345 
2346     /** Implement the Parcelable interface {@hide} */
describeContents()2347     public int describeContents() {
2348         return 0;
2349     }
2350 
2351     /** @hide */
setPasspointManagementObjectTree(String passpointManagementObjectTree)2352     public void setPasspointManagementObjectTree(String passpointManagementObjectTree) {
2353         mPasspointManagementObjectTree = passpointManagementObjectTree;
2354     }
2355 
2356     /** @hide */
getMoTree()2357     public String getMoTree() {
2358         return mPasspointManagementObjectTree;
2359     }
2360 
2361     /** copy constructor {@hide} */
2362     @UnsupportedAppUsage
WifiConfiguration(WifiConfiguration source)2363     public WifiConfiguration(WifiConfiguration source) {
2364         if (source != null) {
2365             networkId = source.networkId;
2366             status = source.status;
2367             SSID = source.SSID;
2368             BSSID = source.BSSID;
2369             FQDN = source.FQDN;
2370             roamingConsortiumIds = source.roamingConsortiumIds.clone();
2371             providerFriendlyName = source.providerFriendlyName;
2372             isHomeProviderNetwork = source.isHomeProviderNetwork;
2373             preSharedKey = source.preSharedKey;
2374 
2375             mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus());
2376             apBand = source.apBand;
2377             apChannel = source.apChannel;
2378 
2379             wepKeys = new String[4];
2380             for (int i = 0; i < wepKeys.length; i++) {
2381                 wepKeys[i] = source.wepKeys[i];
2382             }
2383 
2384             wepTxKeyIndex = source.wepTxKeyIndex;
2385             priority = source.priority;
2386             hiddenSSID = source.hiddenSSID;
2387             allowedKeyManagement   = (BitSet) source.allowedKeyManagement.clone();
2388             allowedProtocols       = (BitSet) source.allowedProtocols.clone();
2389             allowedAuthAlgorithms  = (BitSet) source.allowedAuthAlgorithms.clone();
2390             allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone();
2391             allowedGroupCiphers    = (BitSet) source.allowedGroupCiphers.clone();
2392             allowedGroupManagementCiphers = (BitSet) source.allowedGroupManagementCiphers.clone();
2393             allowedSuiteBCiphers    = (BitSet) source.allowedSuiteBCiphers.clone();
2394             enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
2395 
2396             defaultGwMacAddress = source.defaultGwMacAddress;
2397 
2398             mIpConfiguration = new IpConfiguration(source.mIpConfiguration);
2399 
2400             if ((source.linkedConfigurations != null)
2401                     && (source.linkedConfigurations.size() > 0)) {
2402                 linkedConfigurations = new HashMap<String, Integer>();
2403                 linkedConfigurations.putAll(source.linkedConfigurations);
2404             }
2405             mCachedConfigKey = null; //force null configKey
2406             selfAdded = source.selfAdded;
2407             validatedInternetAccess = source.validatedInternetAccess;
2408             isLegacyPasspointConfig = source.isLegacyPasspointConfig;
2409             ephemeral = source.ephemeral;
2410             osu = source.osu;
2411             trusted = source.trusted;
2412             fromWifiNetworkSuggestion = source.fromWifiNetworkSuggestion;
2413             fromWifiNetworkSpecifier = source.fromWifiNetworkSpecifier;
2414             meteredHint = source.meteredHint;
2415             meteredOverride = source.meteredOverride;
2416             useExternalScores = source.useExternalScores;
2417 
2418             didSelfAdd = source.didSelfAdd;
2419             lastConnectUid = source.lastConnectUid;
2420             lastUpdateUid = source.lastUpdateUid;
2421             creatorUid = source.creatorUid;
2422             creatorName = source.creatorName;
2423             lastUpdateName = source.lastUpdateName;
2424             peerWifiConfiguration = source.peerWifiConfiguration;
2425 
2426             lastConnected = source.lastConnected;
2427             lastDisconnected = source.lastDisconnected;
2428             numScorerOverride = source.numScorerOverride;
2429             numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
2430             numAssociation = source.numAssociation;
2431             userApproved = source.userApproved;
2432             numNoInternetAccessReports = source.numNoInternetAccessReports;
2433             noInternetAccessExpected = source.noInternetAccessExpected;
2434             creationTime = source.creationTime;
2435             updateTime = source.updateTime;
2436             shared = source.shared;
2437             recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus());
2438             mRandomizedMacAddress = source.mRandomizedMacAddress;
2439             macRandomizationSetting = source.macRandomizationSetting;
2440             requirePMF = source.requirePMF;
2441             updateIdentifier = source.updateIdentifier;
2442         }
2443     }
2444 
2445     /** Implement the Parcelable interface {@hide} */
2446     @Override
writeToParcel(Parcel dest, int flags)2447     public void writeToParcel(Parcel dest, int flags) {
2448         dest.writeInt(networkId);
2449         dest.writeInt(status);
2450         mNetworkSelectionStatus.writeToParcel(dest);
2451         dest.writeString(SSID);
2452         dest.writeString(BSSID);
2453         dest.writeInt(apBand);
2454         dest.writeInt(apChannel);
2455         dest.writeString(FQDN);
2456         dest.writeString(providerFriendlyName);
2457         dest.writeInt(isHomeProviderNetwork ? 1 : 0);
2458         dest.writeInt(roamingConsortiumIds.length);
2459         for (long roamingConsortiumId : roamingConsortiumIds) {
2460             dest.writeLong(roamingConsortiumId);
2461         }
2462         dest.writeString(preSharedKey);
2463         for (String wepKey : wepKeys) {
2464             dest.writeString(wepKey);
2465         }
2466         dest.writeInt(wepTxKeyIndex);
2467         dest.writeInt(priority);
2468         dest.writeInt(hiddenSSID ? 1 : 0);
2469         dest.writeInt(requirePMF ? 1 : 0);
2470         dest.writeString(updateIdentifier);
2471 
2472         writeBitSet(dest, allowedKeyManagement);
2473         writeBitSet(dest, allowedProtocols);
2474         writeBitSet(dest, allowedAuthAlgorithms);
2475         writeBitSet(dest, allowedPairwiseCiphers);
2476         writeBitSet(dest, allowedGroupCiphers);
2477         writeBitSet(dest, allowedGroupManagementCiphers);
2478         writeBitSet(dest, allowedSuiteBCiphers);
2479 
2480         dest.writeParcelable(enterpriseConfig, flags);
2481 
2482         dest.writeParcelable(mIpConfiguration, flags);
2483         dest.writeString(dhcpServer);
2484         dest.writeString(defaultGwMacAddress);
2485         dest.writeInt(selfAdded ? 1 : 0);
2486         dest.writeInt(didSelfAdd ? 1 : 0);
2487         dest.writeInt(validatedInternetAccess ? 1 : 0);
2488         dest.writeInt(isLegacyPasspointConfig ? 1 : 0);
2489         dest.writeInt(ephemeral ? 1 : 0);
2490         dest.writeInt(trusted ? 1 : 0);
2491         dest.writeInt(fromWifiNetworkSuggestion ? 1 : 0);
2492         dest.writeInt(fromWifiNetworkSpecifier ? 1 : 0);
2493         dest.writeInt(meteredHint ? 1 : 0);
2494         dest.writeInt(meteredOverride);
2495         dest.writeInt(useExternalScores ? 1 : 0);
2496         dest.writeInt(creatorUid);
2497         dest.writeInt(lastConnectUid);
2498         dest.writeInt(lastUpdateUid);
2499         dest.writeString(creatorName);
2500         dest.writeString(lastUpdateName);
2501         dest.writeInt(numScorerOverride);
2502         dest.writeInt(numScorerOverrideAndSwitchedNetwork);
2503         dest.writeInt(numAssociation);
2504         dest.writeInt(userApproved);
2505         dest.writeInt(numNoInternetAccessReports);
2506         dest.writeInt(noInternetAccessExpected ? 1 : 0);
2507         dest.writeInt(shared ? 1 : 0);
2508         dest.writeString(mPasspointManagementObjectTree);
2509         dest.writeInt(recentFailure.getAssociationStatus());
2510         dest.writeParcelable(mRandomizedMacAddress, flags);
2511         dest.writeInt(macRandomizationSetting);
2512         dest.writeInt(osu ? 1 : 0);
2513     }
2514 
2515     /** Implement the Parcelable interface {@hide} */
2516     @UnsupportedAppUsage
2517     public static final @android.annotation.NonNull Creator<WifiConfiguration> CREATOR =
2518         new Creator<WifiConfiguration>() {
2519             public WifiConfiguration createFromParcel(Parcel in) {
2520                 WifiConfiguration config = new WifiConfiguration();
2521                 config.networkId = in.readInt();
2522                 config.status = in.readInt();
2523                 config.mNetworkSelectionStatus.readFromParcel(in);
2524                 config.SSID = in.readString();
2525                 config.BSSID = in.readString();
2526                 config.apBand = in.readInt();
2527                 config.apChannel = in.readInt();
2528                 config.FQDN = in.readString();
2529                 config.providerFriendlyName = in.readString();
2530                 config.isHomeProviderNetwork = in.readInt() != 0;
2531                 int numRoamingConsortiumIds = in.readInt();
2532                 config.roamingConsortiumIds = new long[numRoamingConsortiumIds];
2533                 for (int i = 0; i < numRoamingConsortiumIds; i++) {
2534                     config.roamingConsortiumIds[i] = in.readLong();
2535                 }
2536                 config.preSharedKey = in.readString();
2537                 for (int i = 0; i < config.wepKeys.length; i++) {
2538                     config.wepKeys[i] = in.readString();
2539                 }
2540                 config.wepTxKeyIndex = in.readInt();
2541                 config.priority = in.readInt();
2542                 config.hiddenSSID = in.readInt() != 0;
2543                 config.requirePMF = in.readInt() != 0;
2544                 config.updateIdentifier = in.readString();
2545 
2546                 config.allowedKeyManagement   = readBitSet(in);
2547                 config.allowedProtocols       = readBitSet(in);
2548                 config.allowedAuthAlgorithms  = readBitSet(in);
2549                 config.allowedPairwiseCiphers = readBitSet(in);
2550                 config.allowedGroupCiphers    = readBitSet(in);
2551                 config.allowedGroupManagementCiphers = readBitSet(in);
2552                 config.allowedSuiteBCiphers   = readBitSet(in);
2553 
2554                 config.enterpriseConfig = in.readParcelable(null);
2555                 config.setIpConfiguration(in.readParcelable(null));
2556                 config.dhcpServer = in.readString();
2557                 config.defaultGwMacAddress = in.readString();
2558                 config.selfAdded = in.readInt() != 0;
2559                 config.didSelfAdd = in.readInt() != 0;
2560                 config.validatedInternetAccess = in.readInt() != 0;
2561                 config.isLegacyPasspointConfig = in.readInt() != 0;
2562                 config.ephemeral = in.readInt() != 0;
2563                 config.trusted = in.readInt() != 0;
2564                 config.fromWifiNetworkSuggestion =  in.readInt() != 0;
2565                 config.fromWifiNetworkSpecifier =  in.readInt() != 0;
2566                 config.meteredHint = in.readInt() != 0;
2567                 config.meteredOverride = in.readInt();
2568                 config.useExternalScores = in.readInt() != 0;
2569                 config.creatorUid = in.readInt();
2570                 config.lastConnectUid = in.readInt();
2571                 config.lastUpdateUid = in.readInt();
2572                 config.creatorName = in.readString();
2573                 config.lastUpdateName = in.readString();
2574                 config.numScorerOverride = in.readInt();
2575                 config.numScorerOverrideAndSwitchedNetwork = in.readInt();
2576                 config.numAssociation = in.readInt();
2577                 config.userApproved = in.readInt();
2578                 config.numNoInternetAccessReports = in.readInt();
2579                 config.noInternetAccessExpected = in.readInt() != 0;
2580                 config.shared = in.readInt() != 0;
2581                 config.mPasspointManagementObjectTree = in.readString();
2582                 config.recentFailure.setAssociationStatus(in.readInt());
2583                 config.mRandomizedMacAddress = in.readParcelable(null);
2584                 config.macRandomizationSetting = in.readInt();
2585                 config.osu = in.readInt() != 0;
2586                 return config;
2587             }
2588 
2589             public WifiConfiguration[] newArray(int size) {
2590                 return new WifiConfiguration[size];
2591             }
2592         };
2593 
2594     /**
2595      * Serializes the object for backup
2596      * @hide
2597      */
getBytesForBackup()2598     public byte[] getBytesForBackup() throws IOException {
2599         ByteArrayOutputStream baos = new ByteArrayOutputStream();
2600         DataOutputStream out = new DataOutputStream(baos);
2601 
2602         out.writeInt(BACKUP_VERSION);
2603         BackupUtils.writeString(out, SSID);
2604         out.writeInt(apBand);
2605         out.writeInt(apChannel);
2606         BackupUtils.writeString(out, preSharedKey);
2607         out.writeInt(getAuthType());
2608         out.writeBoolean(hiddenSSID);
2609         return baos.toByteArray();
2610     }
2611 
2612     /**
2613      * Deserializes a byte array into the WiFiConfiguration Object
2614      * @hide
2615      */
getWifiConfigFromBackup(DataInputStream in)2616     public static WifiConfiguration getWifiConfigFromBackup(DataInputStream in) throws IOException,
2617             BackupUtils.BadVersionException {
2618         WifiConfiguration config = new WifiConfiguration();
2619         int version = in.readInt();
2620         if (version < 1 || version > BACKUP_VERSION) {
2621             throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
2622         }
2623 
2624         if (version == 1) return null; // Version 1 is a bad dataset.
2625 
2626         config.SSID = BackupUtils.readString(in);
2627         config.apBand = in.readInt();
2628         config.apChannel = in.readInt();
2629         config.preSharedKey = BackupUtils.readString(in);
2630         config.allowedKeyManagement.set(in.readInt());
2631         if (version >= 3) {
2632             config.hiddenSSID = in.readBoolean();
2633         }
2634         return config;
2635     }
2636 }
2637