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