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