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