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.os.Parcel;
26 import android.os.Parcelable;
27 import android.text.TextUtils;
28 import android.util.Log;
29 
30 import java.util.HashMap;
31 import java.util.BitSet;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.Comparator;
35 import java.util.HashSet;
36 
37 /**
38  * A class representing a configured Wi-Fi network, including the
39  * security configuration.
40  */
41 public class WifiConfiguration implements Parcelable {
42     private static final String TAG = "WifiConfiguration";
43     /** {@hide} */
44     public static final String ssidVarName = "ssid";
45     /** {@hide} */
46     public static final String bssidVarName = "bssid";
47     /** {@hide} */
48     public static final String pskVarName = "psk";
49     /** {@hide} */
50     public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" };
51     /** {@hide} */
52     public static final String wepTxKeyIdxVarName = "wep_tx_keyidx";
53     /** {@hide} */
54     public static final String priorityVarName = "priority";
55     /** {@hide} */
56     public static final String hiddenSSIDVarName = "scan_ssid";
57     /** {@hide} */
58     public static final String pmfVarName = "ieee80211w";
59     /** {@hide} */
60     public static final String updateIdentiferVarName = "update_identifier";
61     /** {@hide} */
62     public static final int INVALID_NETWORK_ID = -1;
63 
64     /**
65      * Recognized key management schemes.
66      */
67     public static class KeyMgmt {
KeyMgmt()68         private KeyMgmt() { }
69 
70         /** WPA is not used; plaintext or static WEP could be used. */
71         public static final int NONE = 0;
72         /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */
73         public static final int WPA_PSK = 1;
74         /** WPA using EAP authentication. Generally used with an external authentication server. */
75         public static final int WPA_EAP = 2;
76         /** IEEE 802.1X using EAP authentication and (optionally) dynamically
77          * generated WEP keys. */
78         public static final int IEEE8021X = 3;
79 
80         /** WPA2 pre-shared key for use with soft access point
81           * (requires {@code preSharedKey} to be specified).
82           * @hide
83           */
84         public static final int WPA2_PSK = 4;
85 
86         public static final String varName = "key_mgmt";
87 
88         public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X",
89                 "WPA2_PSK" };
90     }
91 
92     /**
93      * Recognized security protocols.
94      */
95     public static class Protocol {
Protocol()96         private Protocol() { }
97 
98         /** WPA/IEEE 802.11i/D3.0 */
99         public static final int WPA = 0;
100         /** WPA2/IEEE 802.11i */
101         public static final int RSN = 1;
102 
103         public static final String varName = "proto";
104 
105         public static final String[] strings = { "WPA", "RSN" };
106     }
107 
108     /**
109      * Recognized IEEE 802.11 authentication algorithms.
110      */
111     public static class AuthAlgorithm {
AuthAlgorithm()112         private AuthAlgorithm() { }
113 
114         /** Open System authentication (required for WPA/WPA2) */
115         public static final int OPEN = 0;
116         /** Shared Key authentication (requires static WEP keys) */
117         public static final int SHARED = 1;
118         /** LEAP/Network EAP (only used with LEAP) */
119         public static final int LEAP = 2;
120 
121         public static final String varName = "auth_alg";
122 
123         public static final String[] strings = { "OPEN", "SHARED", "LEAP" };
124     }
125 
126     /**
127      * Recognized pairwise ciphers for WPA.
128      */
129     public static class PairwiseCipher {
PairwiseCipher()130         private PairwiseCipher() { }
131 
132         /** Use only Group keys (deprecated) */
133         public static final int NONE = 0;
134         /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
135         public static final int TKIP = 1;
136         /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
137         public static final int CCMP = 2;
138 
139         public static final String varName = "pairwise";
140 
141         public static final String[] strings = { "NONE", "TKIP", "CCMP" };
142     }
143 
144     /**
145      * Recognized group ciphers.
146      * <pre>
147      * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
148      * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
149      * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
150      * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
151      * </pre>
152      */
153     public static class GroupCipher {
GroupCipher()154         private GroupCipher() { }
155 
156         /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */
157         public static final int WEP40 = 0;
158         /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */
159         public static final int WEP104 = 1;
160         /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
161         public static final int TKIP = 2;
162         /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
163         public static final int CCMP = 3;
164 
165         public static final String varName = "group";
166 
167         public static final String[] strings = { "WEP40", "WEP104", "TKIP", "CCMP" };
168     }
169 
170     /** Possible status of a network configuration. */
171     public static class Status {
Status()172         private Status() { }
173 
174         /** this is the network we are currently connected to */
175         public static final int CURRENT = 0;
176         /** supplicant will not attempt to use this network */
177         public static final int DISABLED = 1;
178         /** supplicant will consider this network available for association */
179         public static final int ENABLED = 2;
180 
181         public static final String[] strings = { "current", "disabled", "enabled" };
182     }
183 
184     /** @hide */
185     public static final int DISABLED_UNKNOWN_REASON                         = 0;
186     /** @hide */
187     public static final int DISABLED_DNS_FAILURE                            = 1;
188     /** @hide */
189     public static final int DISABLED_DHCP_FAILURE                           = 2;
190     /** @hide */
191     public static final int DISABLED_AUTH_FAILURE                           = 3;
192     /** @hide */
193     public static final int DISABLED_ASSOCIATION_REJECT                     = 4;
194     /** @hide */
195     public static final int DISABLED_BY_WIFI_MANAGER                        = 5;
196 
197     /** @hide */
198     public static final int UNKNOWN_UID = -1;
199 
200     /**
201      * The ID number that the supplicant uses to identify this
202      * network configuration entry. This must be passed as an argument
203      * to most calls into the supplicant.
204      */
205     public int networkId;
206 
207     /**
208      * The current status of this network configuration entry.
209      * @see Status
210      */
211     public int status;
212 
213     /**
214      * The configuration needs to be written to networkHistory.txt
215      * @hide
216      */
217     public boolean dirty;
218 
219     /**
220      * The code referring to a reason for disabling the network
221      * Valid when {@link #status} == Status.DISABLED
222      * @hide
223      */
224     public int disableReason;
225 
226     /**
227      * The network's SSID. Can either be an ASCII string,
228      * which must be enclosed in double quotation marks
229      * (e.g., {@code "MyNetwork"}, or a string of
230      * hex digits,which are not enclosed in quotes
231      * (e.g., {@code 01a243f405}).
232      */
233     public String SSID;
234     /**
235      * When set, this network configuration entry should only be used when
236      * associating with the AP having the specified BSSID. The value is
237      * a string in the format of an Ethernet MAC address, e.g.,
238      * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
239      */
240     public String BSSID;
241 
242     /**
243      * The band which AP resides on
244      * 0-2G  1-5G
245      * By default, 2G is chosen
246      * @hide
247      */
248     public int apBand = 0;
249 
250     /**
251      * The channel which AP resides on,currently, US only
252      * 2G  1-11
253      * 5G  36,40,44,48,149,153,157,161,165
254      * 0 - find a random available channel according to the apBand
255      * @hide
256      */
257     public int apChannel = 0;
258 
259     /**
260      * Pre-shared key for use with WPA-PSK.
261      * <p/>
262      * When the value of this key is read, the actual key is
263      * not returned, just a "*" if the key has a value, or the null
264      * string otherwise.
265      */
266     public String preSharedKey;
267     /**
268      * Up to four WEP keys. Either an ASCII string enclosed in double
269      * quotation marks (e.g., {@code "abcdef"} or a string
270      * of hex digits (e.g., {@code 0102030405}).
271      * <p/>
272      * When the value of one of these keys is read, the actual key is
273      * not returned, just a "*" if the key has a value, or the null
274      * string otherwise.
275      */
276     public String[] wepKeys;
277 
278     /** Default WEP key index, ranging from 0 to 3. */
279     public int wepTxKeyIndex;
280 
281     /**
282      * Priority determines the preference given to a network by {@code wpa_supplicant}
283      * when choosing an access point with which to associate.
284      */
285     public int priority;
286 
287     /**
288      * This is a network that does not broadcast its SSID, so an
289      * SSID-specific probe request must be used for scans.
290      */
291     public boolean hiddenSSID;
292 
293     /**
294      * This is a network that requries Protected Management Frames (PMF).
295      * @hide
296      */
297     public boolean requirePMF;
298 
299     /**
300      * Update identifier, for Passpoint network.
301      * @hide
302      */
303     public String updateIdentifier;
304 
305     /**
306      * The set of key management protocols supported by this configuration.
307      * See {@link KeyMgmt} for descriptions of the values.
308      * Defaults to WPA-PSK WPA-EAP.
309      */
310     public BitSet allowedKeyManagement;
311     /**
312      * The set of security protocols supported by this configuration.
313      * See {@link Protocol} for descriptions of the values.
314      * Defaults to WPA RSN.
315      */
316     public BitSet allowedProtocols;
317     /**
318      * The set of authentication protocols supported by this configuration.
319      * See {@link AuthAlgorithm} for descriptions of the values.
320      * Defaults to automatic selection.
321      */
322     public BitSet allowedAuthAlgorithms;
323     /**
324      * The set of pairwise ciphers for WPA supported by this configuration.
325      * See {@link PairwiseCipher} for descriptions of the values.
326      * Defaults to CCMP TKIP.
327      */
328     public BitSet allowedPairwiseCiphers;
329     /**
330      * The set of group ciphers supported by this configuration.
331      * See {@link GroupCipher} for descriptions of the values.
332      * Defaults to CCMP TKIP WEP104 WEP40.
333      */
334     public BitSet allowedGroupCiphers;
335     /**
336      * The enterprise configuration details specifying the EAP method,
337      * certificates and other settings associated with the EAP.
338      */
339     public WifiEnterpriseConfig enterpriseConfig;
340 
341     /**
342      * Fully qualified domain name of a passpoint configuration
343      */
344     public String FQDN;
345 
346     /**
347      * Name of passpoint credential provider
348      */
349     public String providerFriendlyName;
350 
351     /**
352      * Roaming Consortium Id list for passpoint credential; identifies a set of networks where
353      * passpoint credential will be considered valid
354      */
355     public long[] roamingConsortiumIds;
356 
357     /**
358      * @hide
359      */
360     private IpConfiguration mIpConfiguration;
361 
362     /**
363      * @hide
364      * dhcp server MAC address if known
365      */
366     public String dhcpServer;
367 
368     /**
369      * @hide
370      * default Gateway MAC address if known
371      */
372     public String defaultGwMacAddress;
373 
374     /**
375      * @hide
376      * last failure
377      */
378     public String lastFailure;
379 
380     /**
381      * @hide
382      * last time we connected, this configuration had validated internet access
383      */
384     public boolean validatedInternetAccess;
385 
386     /**
387      * @hide
388      * Uid of app creating the configuration
389      */
390     @SystemApi
391     public int creatorUid;
392 
393     /**
394      * @hide
395      * Uid of last app issuing a connection related command
396      */
397     public int lastConnectUid;
398 
399     /**
400      * @hide
401      * Uid of last app modifying the configuration
402      */
403     @SystemApi
404     public int lastUpdateUid;
405 
406     /**
407      * @hide
408      * Universal name for app creating the configuration
409      *    see {#link {@link PackageManager#getNameForUid(int)}
410      */
411     @SystemApi
412     public String creatorName;
413 
414     /**
415      * @hide
416      * Universal name for app updating the configuration
417      *    see {#link {@link PackageManager#getNameForUid(int)}
418      */
419     @SystemApi
420     public String lastUpdateName;
421 
422     /**
423      * @hide
424      * Uid used by autoJoin
425      */
426     public String autoJoinBSSID;
427 
428     /**
429      * @hide
430      * Status of user approval for connection
431      */
432     public int userApproved = USER_UNSPECIFIED;
433 
434     /** The Below RSSI thresholds are used to configure AutoJoin
435      *  - GOOD/LOW/BAD thresholds are used so as to calculate link score
436      *  - UNWANTED_SOFT are used by the blacklisting logic so as to handle
437      *  the unwanted network message coming from CS
438      *  - UNBLACKLIST thresholds are used so as to tweak the speed at which
439      *  the network is unblacklisted (i.e. if
440      *          it is seen with good RSSI, it is blacklisted faster)
441      *  - INITIAL_AUTOJOIN_ATTEMPT, used to determine how close from
442      *  the network we need to be before autojoin kicks in
443      */
444     /** @hide **/
445     public static int INVALID_RSSI = -127;
446 
447     /** @hide **/
448     public static int UNWANTED_BLACKLIST_SOFT_RSSI_24 = -80;
449 
450     /** @hide **/
451     public static int UNWANTED_BLACKLIST_SOFT_RSSI_5 = -70;
452 
453     /** @hide **/
454     public static int GOOD_RSSI_24 = -65;
455 
456     /** @hide **/
457     public static int LOW_RSSI_24 = -77;
458 
459     /** @hide **/
460     public static int BAD_RSSI_24 = -87;
461 
462     /** @hide **/
463     public static int GOOD_RSSI_5 = -60;
464 
465     /** @hide **/
466     public static int LOW_RSSI_5 = -72;
467 
468     /** @hide **/
469     public static int BAD_RSSI_5 = -82;
470 
471     /** @hide **/
472     public static int UNWANTED_BLACKLIST_SOFT_BUMP = 4;
473 
474     /** @hide **/
475     public static int UNWANTED_BLACKLIST_HARD_BUMP = 8;
476 
477     /** @hide **/
478     public static int UNBLACKLIST_THRESHOLD_24_SOFT = -77;
479 
480     /** @hide **/
481     public static int UNBLACKLIST_THRESHOLD_24_HARD = -68;
482 
483     /** @hide **/
484     public static int UNBLACKLIST_THRESHOLD_5_SOFT = -63;
485 
486     /** @hide **/
487     public static int UNBLACKLIST_THRESHOLD_5_HARD = -56;
488 
489     /** @hide **/
490     public static int INITIAL_AUTO_JOIN_ATTEMPT_MIN_24 = -80;
491 
492     /** @hide **/
493     public static int INITIAL_AUTO_JOIN_ATTEMPT_MIN_5 = -70;
494 
495     /** @hide
496      * 5GHz band is prefered low over 2.4 if the 5GHz RSSI is higher than this threshold */
497     public static int A_BAND_PREFERENCE_RSSI_THRESHOLD = -65;
498 
499     /** @hide
500      * 5GHz band is penalized if the 5GHz RSSI is lower than this threshold **/
501     public static int G_BAND_PREFERENCE_RSSI_THRESHOLD = -75;
502 
503     /** @hide
504      * Boost given to RSSI on a home network for the purpose of calculating the score
505      * This adds stickiness to home networks, as defined by:
506      * - less than 4 known BSSIDs
507      * - PSK only
508      * - TODO: add a test to verify that all BSSIDs are behind same gateway
509      ***/
510     public static int HOME_NETWORK_RSSI_BOOST = 5;
511 
512     /** @hide
513      * RSSI boost for configuration which use autoJoinUseAggressiveJoinAttemptThreshold
514      * To be more aggressive when initially attempting to auto join
515      */
516     public static int MAX_INITIAL_AUTO_JOIN_RSSI_BOOST = 8;
517 
518     /**
519      * @hide
520      * A summary of the RSSI and Band status for that configuration
521      * This is used as a temporary value by the auto-join controller
522      */
523     public static final class Visibility {
524         public int rssi5;   // strongest 5GHz RSSI
525         public int rssi24;  // strongest 2.4GHz RSSI
526         public int num5;    // number of BSSIDs on 5GHz
527         public int num24;   // number of BSSIDs on 2.4GHz
528         public long age5;   // timestamp of the strongest 5GHz BSSID (last time it was seen)
529         public long age24;  // timestamp of the strongest 2.4GHz BSSID (last time it was seen)
530         public String BSSID24;
531         public String BSSID5;
532         public int score; // Debug only, indicate last score used for autojoin/cell-handover
533         public int currentNetworkBoost; // Debug only, indicate boost applied to RSSI if current
534         public int bandPreferenceBoost; // Debug only, indicate boost applied to RSSI if current
535         public int lastChoiceBoost; // Debug only, indicate last choice applied to this configuration
536         public String lastChoiceConfig; // Debug only, indicate last choice applied to this configuration
537 
Visibility()538         public Visibility() {
539             rssi5 = INVALID_RSSI;
540             rssi24 = INVALID_RSSI;
541         }
542 
Visibility(Visibility source)543         public Visibility(Visibility source) {
544             rssi5 = source.rssi5;
545             rssi24 = source.rssi24;
546             age24 = source.age24;
547             age5 = source.age5;
548             num24 = source.num24;
549             num5 = source.num5;
550             BSSID5 = source.BSSID5;
551             BSSID24 = source.BSSID24;
552         }
553 
554         @Override
toString()555         public String toString() {
556             StringBuilder sbuf = new StringBuilder();
557             sbuf.append("[");
558             if (rssi24 > INVALID_RSSI) {
559                 sbuf.append(Integer.toString(rssi24));
560                 sbuf.append(",");
561                 sbuf.append(Integer.toString(num24));
562                 if (BSSID24 != null) sbuf.append(",").append(BSSID24);
563             }
564             sbuf.append("; ");
565             if (rssi5 > INVALID_RSSI) {
566                 sbuf.append(Integer.toString(rssi5));
567                 sbuf.append(",");
568                 sbuf.append(Integer.toString(num5));
569                 if (BSSID5 != null) sbuf.append(",").append(BSSID5);
570             }
571             if (score != 0) {
572                 sbuf.append("; ").append(score);
573                 sbuf.append(", ").append(currentNetworkBoost);
574                 sbuf.append(", ").append(bandPreferenceBoost);
575                 if (lastChoiceConfig != null) {
576                     sbuf.append(", ").append(lastChoiceBoost);
577                     sbuf.append(", ").append(lastChoiceConfig);
578                 }
579             }
580             sbuf.append("]");
581             return sbuf.toString();
582         }
583     }
584 
585     /** @hide
586      * Cache the visibility status of this configuration.
587      * Visibility can change at any time depending on scan results availability.
588      * Owner of the WifiConfiguration is responsible to set this field based on
589      * recent scan results.
590      ***/
591     public Visibility visibility;
592 
593     /** @hide
594      * calculate and set Visibility for that configuration.
595      *
596      * age in milliseconds: we will consider only ScanResults that are more recent,
597      * i.e. younger.
598      ***/
setVisibility(Visibility status)599     public void setVisibility(Visibility status) {
600         visibility = status;
601     }
602 
603     /** @hide */
604     public static final int AUTO_JOIN_ENABLED                   = 0;
605     /**
606      * if this is set, the WifiConfiguration cannot use linkages so as to bump
607      * it's relative priority.
608      * - status between and 128 indicate various level of blacklisting depending
609      * on the severity or frequency of the connection error
610      * - deleted status indicates that the user is deleting the configuration, and so
611      * although it may have been self added we will not re-self-add it, ignore it,
612      * not return it to applications, and not connect to it
613      * */
614 
615     /** @hide
616      * network was temporary disabled due to bad connection, most likely due
617      * to weak RSSI */
618     public static final int AUTO_JOIN_TEMPORARY_DISABLED  = 1;
619     /** @hide
620      * network was temporary disabled due to bad connection, which cant be attributed
621      * to weak RSSI */
622     public static final int AUTO_JOIN_TEMPORARY_DISABLED_LINK_ERRORS  = 32;
623     /** @hide */
624     public static final int AUTO_JOIN_TEMPORARY_DISABLED_AT_SUPPLICANT  = 64;
625     /** @hide */
626     public static final int AUTO_JOIN_DISABLED_ON_AUTH_FAILURE  = 128;
627     /** @hide */
628     public static final int AUTO_JOIN_DISABLED_NO_CREDENTIALS = 160;
629     /** @hide */
630     public static final int AUTO_JOIN_DISABLED_USER_ACTION = 161;
631 
632     /** @hide */
633     public static final int AUTO_JOIN_DELETED  = 200;
634 
635     // States for the userApproved field
636     /**
637      * @hide
638      * User hasn't specified if connection is okay
639      */
640     public static final int USER_UNSPECIFIED = 0;
641     /**
642      * @hide
643      * User has approved this for connection
644      */
645     public static final int USER_APPROVED = 1;
646     /**
647      * @hide
648      * User has banned this from connection
649      */
650     public static final int USER_BANNED = 2;
651     /**
652      * @hide
653      * Waiting for user input
654      */
655     public static final int USER_PENDING = 3;
656 
657     /**
658      * @hide
659      */
660     public int autoJoinStatus;
661 
662     /**
663      * @hide
664      * Number of connection failures
665      */
666     public int numConnectionFailures;
667 
668     /**
669      * @hide
670      * Number of IP config failures
671      */
672     public int numIpConfigFailures;
673 
674     /**
675      * @hide
676      * Number of Auth failures
677      */
678     public int numAuthFailures;
679 
680     /**
681      * @hide
682      * Number of reports indicating no Internet Access
683      */
684     public int numNoInternetAccessReports;
685 
686     /**
687      * @hide
688      * For debug: date at which the config was last updated
689      */
690     public String updateTime;
691 
692     /**
693      * @hide
694      * For debug: date at which the config was last updated
695      */
696     public String creationTime;
697 
698     /**
699      * @hide
700      * The WiFi configuration is considered to have no internet access for purpose of autojoining
701      * if there has been a report of it having no internet access, and, it never have had
702      * internet access in the past.
703      */
hasNoInternetAccess()704     public boolean hasNoInternetAccess() {
705         return numNoInternetAccessReports > 0 && !validatedInternetAccess;
706     }
707 
708     /**
709      * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a
710      * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to
711      * this configuration and selects "don't ask again".
712      * @hide
713      */
714     public boolean noInternetAccessExpected;
715 
716     /**
717      * @hide
718      * Last time we blacklisted the configuration
719      */
720     public long blackListTimestamp;
721 
722     /**
723      * @hide
724      * Last time the system was connected to this configuration.
725      */
726     public long lastConnected;
727 
728     /**
729      * @hide
730      * Last time the system tried to connect and failed.
731      */
732     public long lastConnectionFailure;
733 
734     /**
735      * @hide
736      * Last time the system tried to roam and failed because of authentication failure or DHCP
737      * RENEW failure.
738      */
739     public long lastRoamingFailure;
740 
741     /** @hide */
742     public static int ROAMING_FAILURE_IP_CONFIG = 1;
743     /** @hide */
744     public static int ROAMING_FAILURE_AUTH_FAILURE = 2;
745 
746     /**
747      * @hide
748      * Initial amount of time this Wifi configuration gets blacklisted for network switching
749      * because of roaming failure
750      */
751     public long roamingFailureBlackListTimeMilli = 1000;
752 
753     /**
754      * @hide
755      * Last roaming failure reason code
756      */
757     public int lastRoamingFailureReason;
758 
759     /**
760      * @hide
761      * Last time the system was disconnected to this configuration.
762      */
763     public long lastDisconnected;
764 
765     /**
766      * Set if the configuration was self added by the framework
767      * This boolean is cleared if we get a connect/save/ update or
768      * any wifiManager command that indicate the user interacted with the configuration
769      * since we will now consider that the configuration belong to him.
770      * @hide
771      */
772     public boolean selfAdded;
773 
774     /**
775      * Set if the configuration was self added by the framework
776      * This boolean is set once and never cleared. It is used
777      * so as we never loose track of who created the
778      * configuration in the first place.
779      * @hide
780      */
781     public boolean didSelfAdd;
782 
783     /**
784      * Peer WifiConfiguration this WifiConfiguration was added for
785      * @hide
786      */
787     public String peerWifiConfiguration;
788 
789     /**
790      * @hide
791      * Indicate that a WifiConfiguration is temporary and should not be saved
792      * nor considered by AutoJoin.
793      */
794     public boolean ephemeral;
795 
796     /**
797      * @hide
798      * Indicate that we didn't auto-join because rssi was too low
799      */
800     public boolean autoJoinBailedDueToLowRssi;
801 
802     /**
803      * @hide
804      * AutoJoin even though RSSI is 10dB below threshold
805      */
806     public int autoJoinUseAggressiveJoinAttemptThreshold;
807 
808     /**
809      * @hide
810      * Number of time the scorer overrode a the priority based choice, when comparing two
811      * WifiConfigurations, note that since comparing WifiConfiguration happens very often
812      * potentially at every scan, this number might become very large, even on an idle
813      * system.
814      */
815     @SystemApi
816     public int numScorerOverride;
817 
818     /**
819      * @hide
820      * Number of time the scorer overrode a the priority based choice, and the comparison
821      * triggered a network switch
822      */
823     @SystemApi
824     public int numScorerOverrideAndSwitchedNetwork;
825 
826     /**
827      * @hide
828      * Number of time we associated to this configuration.
829      */
830     @SystemApi
831     public int numAssociation;
832 
833     /**
834      * @hide
835      * Number of time user disabled WiFi while associated to this configuration with Low RSSI.
836      */
837     public int numUserTriggeredWifiDisableLowRSSI;
838 
839     /**
840      * @hide
841      * Number of time user disabled WiFi while associated to this configuration with Bad RSSI.
842      */
843     public int numUserTriggeredWifiDisableBadRSSI;
844 
845     /**
846      * @hide
847      * Number of time user disabled WiFi while associated to this configuration
848      * and RSSI was not HIGH.
849      */
850     public int numUserTriggeredWifiDisableNotHighRSSI;
851 
852     /**
853      * @hide
854      * Number of ticks associated to this configuration with Low RSSI.
855      */
856     public int numTicksAtLowRSSI;
857 
858     /**
859      * @hide
860      * Number of ticks associated to this configuration with Bad RSSI.
861      */
862     public int numTicksAtBadRSSI;
863 
864     /**
865      * @hide
866      * Number of ticks associated to this configuration
867      * and RSSI was not HIGH.
868      */
869     public int numTicksAtNotHighRSSI;
870     /**
871      * @hide
872      * Number of time user (WifiManager) triggered association to this configuration.
873      * TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps
874      */
875     public int numUserTriggeredJoinAttempts;
876 
877     /**
878      * @hide
879      * Connect choices
880      *
881      * remember the keys identifying the known WifiConfiguration over which this configuration
882      * was preferred by user or a "WiFi Network Management app", that is,
883      * a WifiManager.CONNECT_NETWORK or SELECT_NETWORK was received while this configuration
884      * was visible to the user:
885      * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP
886      *
887      * The integer represents the configuration's RSSI at that time (useful?)
888      *
889      * The overall auto-join algorithm make use of past connect choice so as to sort configuration,
890      * the exact algorithm still fluctuating as of 5/7/2014
891      *
892      */
893     public HashMap<String, Integer> connectChoices;
894 
895     /**
896      * @hide
897      * Linked Configurations: represent the set of Wificonfigurations that are equivalent
898      * regarding roaming and auto-joining.
899      * The linked configuration may or may not have same SSID, and may or may not have same
900      * credentials.
901      * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server.
902      */
903     public HashMap<String, Integer>  linkedConfigurations;
904 
WifiConfiguration()905     public WifiConfiguration() {
906         networkId = INVALID_NETWORK_ID;
907         SSID = null;
908         BSSID = null;
909         FQDN = null;
910         roamingConsortiumIds = new long[0];
911         priority = 0;
912         hiddenSSID = false;
913         disableReason = DISABLED_UNKNOWN_REASON;
914         allowedKeyManagement = new BitSet();
915         allowedProtocols = new BitSet();
916         allowedAuthAlgorithms = new BitSet();
917         allowedPairwiseCiphers = new BitSet();
918         allowedGroupCiphers = new BitSet();
919         wepKeys = new String[4];
920         for (int i = 0; i < wepKeys.length; i++) {
921             wepKeys[i] = null;
922         }
923         enterpriseConfig = new WifiEnterpriseConfig();
924         autoJoinStatus = AUTO_JOIN_ENABLED;
925         selfAdded = false;
926         didSelfAdd = false;
927         ephemeral = false;
928         validatedInternetAccess = false;
929         mIpConfiguration = new IpConfiguration();
930         lastUpdateUid = -1;
931         creatorUid = -1;
932     }
933 
934     /**
935      * Identify if this configuration represents a passpoint network
936      */
isPasspoint()937     public boolean isPasspoint() {
938         return !TextUtils.isEmpty(FQDN)
939                 && !TextUtils.isEmpty(providerFriendlyName)
940                 && enterpriseConfig != null
941                 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
942     }
943 
944     /**
945      * Helper function, identify if a configuration is linked
946      * @hide
947      */
isLinked(WifiConfiguration config)948     public boolean isLinked(WifiConfiguration config) {
949         if (config.linkedConfigurations != null && linkedConfigurations != null) {
950             if (config.linkedConfigurations.get(configKey()) != null
951                     && linkedConfigurations.get(config.configKey()) != null) {
952                 return true;
953             }
954         }
955         return  false;
956     }
957 
958     /**
959      * Helper function, idenfity if a configuration should be treated as an enterprise network
960      * @hide
961      */
isEnterprise()962     public boolean isEnterprise() {
963         return allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
964             allowedKeyManagement.get(KeyMgmt.IEEE8021X);
965     }
966 
967     /** @hide **/
setAutoJoinStatus(int status)968     public void setAutoJoinStatus(int status) {
969         if (status < 0) status = 0;
970         if (status == 0) {
971             blackListTimestamp = 0;
972         }  else if (status > autoJoinStatus) {
973             blackListTimestamp = System.currentTimeMillis();
974         }
975         if (status != autoJoinStatus) {
976             autoJoinStatus = status;
977             dirty = true;
978         }
979     }
980 
981     @Override
toString()982     public String toString() {
983         StringBuilder sbuf = new StringBuilder();
984         if (this.status == WifiConfiguration.Status.CURRENT) {
985             sbuf.append("* ");
986         } else if (this.status == WifiConfiguration.Status.DISABLED) {
987             sbuf.append("- DSBLE ");
988         }
989         sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
990                 append(" PROVIDER-NAME: ").append(this.providerFriendlyName).
991                 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN).
992                 append(" PRIO: ").append(this.priority).
993                 append('\n');
994         if (this.numConnectionFailures > 0) {
995             sbuf.append(" numConnectFailures ").append(this.numConnectionFailures).append("\n");
996         }
997         if (this.numIpConfigFailures > 0) {
998             sbuf.append(" numIpConfigFailures ").append(this.numIpConfigFailures).append("\n");
999         }
1000         if (this.numAuthFailures > 0) {
1001             sbuf.append(" numAuthFailures ").append(this.numAuthFailures).append("\n");
1002         }
1003         if (this.autoJoinStatus > 0) {
1004             sbuf.append(" autoJoinStatus ").append(this.autoJoinStatus).append("\n");
1005         }
1006         if (this.disableReason > 0) {
1007             sbuf.append(" disableReason ").append(this.disableReason).append("\n");
1008         }
1009         if (this.numAssociation > 0) {
1010             sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
1011         }
1012         if (this.numNoInternetAccessReports > 0) {
1013             sbuf.append(" numNoInternetAccessReports ");
1014             sbuf.append(this.numNoInternetAccessReports).append("\n");
1015         }
1016         if (this.updateTime != null) {
1017             sbuf.append("update ").append(this.updateTime).append("\n");
1018         }
1019         if (this.creationTime != null) {
1020             sbuf.append("creation").append(this.creationTime).append("\n");
1021         }
1022         if (this.didSelfAdd) sbuf.append(" didSelfAdd");
1023         if (this.selfAdded) sbuf.append(" selfAdded");
1024         if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess");
1025         if (this.ephemeral) sbuf.append(" ephemeral");
1026         if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess || this.ephemeral) {
1027             sbuf.append("\n");
1028         }
1029         sbuf.append(" KeyMgmt:");
1030         for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
1031             if (this.allowedKeyManagement.get(k)) {
1032                 sbuf.append(" ");
1033                 if (k < KeyMgmt.strings.length) {
1034                     sbuf.append(KeyMgmt.strings[k]);
1035                 } else {
1036                     sbuf.append("??");
1037                 }
1038             }
1039         }
1040         sbuf.append(" Protocols:");
1041         for (int p = 0; p < this.allowedProtocols.size(); p++) {
1042             if (this.allowedProtocols.get(p)) {
1043                 sbuf.append(" ");
1044                 if (p < Protocol.strings.length) {
1045                     sbuf.append(Protocol.strings[p]);
1046                 } else {
1047                     sbuf.append("??");
1048                 }
1049             }
1050         }
1051         sbuf.append('\n');
1052         sbuf.append(" AuthAlgorithms:");
1053         for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) {
1054             if (this.allowedAuthAlgorithms.get(a)) {
1055                 sbuf.append(" ");
1056                 if (a < AuthAlgorithm.strings.length) {
1057                     sbuf.append(AuthAlgorithm.strings[a]);
1058                 } else {
1059                     sbuf.append("??");
1060                 }
1061             }
1062         }
1063         sbuf.append('\n');
1064         sbuf.append(" PairwiseCiphers:");
1065         for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) {
1066             if (this.allowedPairwiseCiphers.get(pc)) {
1067                 sbuf.append(" ");
1068                 if (pc < PairwiseCipher.strings.length) {
1069                     sbuf.append(PairwiseCipher.strings[pc]);
1070                 } else {
1071                     sbuf.append("??");
1072                 }
1073             }
1074         }
1075         sbuf.append('\n');
1076         sbuf.append(" GroupCiphers:");
1077         for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) {
1078             if (this.allowedGroupCiphers.get(gc)) {
1079                 sbuf.append(" ");
1080                 if (gc < GroupCipher.strings.length) {
1081                     sbuf.append(GroupCipher.strings[gc]);
1082                 } else {
1083                     sbuf.append("??");
1084                 }
1085             }
1086         }
1087         sbuf.append('\n').append(" PSK: ");
1088         if (this.preSharedKey != null) {
1089             sbuf.append('*');
1090         }
1091         sbuf.append("\nEnterprise config:\n");
1092         sbuf.append(enterpriseConfig);
1093 
1094         sbuf.append("IP config:\n");
1095         sbuf.append(mIpConfiguration.toString());
1096 
1097         if (this.autoJoinBSSID != null) sbuf.append(" autoJoinBSSID=" + autoJoinBSSID);
1098         long now_ms = System.currentTimeMillis();
1099         if (this.blackListTimestamp != 0) {
1100             sbuf.append('\n');
1101             long diff = now_ms - this.blackListTimestamp;
1102             if (diff <= 0) {
1103                 sbuf.append(" blackListed since <incorrect>");
1104             } else {
1105                 sbuf.append(" blackListed: ").append(Long.toString(diff/1000)).append( "sec ");
1106             }
1107         }
1108         if (creatorUid != 0)  sbuf.append(" cuid=" + Integer.toString(creatorUid));
1109         if (creatorName != null) sbuf.append(" cname=" + creatorName);
1110         if (lastUpdateUid != 0) sbuf.append(" luid=" + lastUpdateUid);
1111         if (lastUpdateName != null) sbuf.append(" lname=" + lastUpdateName);
1112         sbuf.append(" lcuid=" + lastConnectUid);
1113         sbuf.append(" userApproved=" + userApprovedAsString(userApproved));
1114         sbuf.append(" noInternetAccessExpected=" + noInternetAccessExpected);
1115         sbuf.append(" ");
1116 
1117         if (this.lastConnected != 0) {
1118             sbuf.append('\n');
1119             long diff = now_ms - this.lastConnected;
1120             if (diff <= 0) {
1121                 sbuf.append("lastConnected since <incorrect>");
1122             } else {
1123                 sbuf.append("lastConnected: ").append(Long.toString(diff/1000)).append( "sec ");
1124             }
1125         }
1126         if (this.lastConnectionFailure != 0) {
1127             sbuf.append('\n');
1128             long diff = now_ms - this.lastConnectionFailure;
1129             if (diff <= 0) {
1130                 sbuf.append("lastConnectionFailure since <incorrect> ");
1131             } else {
1132                 sbuf.append("lastConnectionFailure: ").append(Long.toString(diff/1000));
1133                 sbuf.append( "sec ");
1134             }
1135         }
1136         if (this.lastRoamingFailure != 0) {
1137             sbuf.append('\n');
1138             long diff = now_ms - this.lastRoamingFailure;
1139             if (diff <= 0) {
1140                 sbuf.append("lastRoamingFailure since <incorrect> ");
1141             } else {
1142                 sbuf.append("lastRoamingFailure: ").append(Long.toString(diff/1000));
1143                 sbuf.append( "sec ");
1144             }
1145         }
1146         sbuf.append("roamingFailureBlackListTimeMilli: ").
1147                 append(Long.toString(this.roamingFailureBlackListTimeMilli));
1148         sbuf.append('\n');
1149         if (this.linkedConfigurations != null) {
1150             for(String key : this.linkedConfigurations.keySet()) {
1151                 sbuf.append(" linked: ").append(key);
1152                 sbuf.append('\n');
1153             }
1154         }
1155         if (this.connectChoices != null) {
1156             for(String key : this.connectChoices.keySet()) {
1157                 Integer choice = this.connectChoices.get(key);
1158                 if (choice != null) {
1159                     sbuf.append(" choice: ").append(key);
1160                     sbuf.append(" = ").append(choice);
1161                     sbuf.append('\n');
1162                 }
1163             }
1164         }
1165         sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI);
1166         sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI);
1167         sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI);
1168         sbuf.append('\n');
1169         sbuf.append("ticksLow: ").append(this.numTicksAtLowRSSI);
1170         sbuf.append(" ticksBad: ").append(this.numTicksAtBadRSSI);
1171         sbuf.append(" ticksNotHigh: ").append(this.numTicksAtNotHighRSSI);
1172         sbuf.append('\n');
1173         sbuf.append("triggeredJoin: ").append(this.numUserTriggeredJoinAttempts);
1174         sbuf.append('\n');
1175         sbuf.append("autoJoinBailedDueToLowRssi: ").append(this.autoJoinBailedDueToLowRssi);
1176         sbuf.append('\n');
1177         sbuf.append("autoJoinUseAggressiveJoinAttemptThreshold: ");
1178         sbuf.append(this.autoJoinUseAggressiveJoinAttemptThreshold);
1179         sbuf.append('\n');
1180 
1181         return sbuf.toString();
1182     }
1183 
1184     /**
1185      * Construct a WifiConfiguration from a scanned network
1186      * @param scannedAP the scan result used to construct the config entry
1187      * TODO: figure out whether this is a useful way to construct a new entry.
1188      *
1189     public WifiConfiguration(ScanResult scannedAP) {
1190         networkId = -1;
1191         SSID = scannedAP.SSID;
1192         BSSID = scannedAP.BSSID;
1193     }
1194     */
1195 
1196     /** {@hide} */
getPrintableSsid()1197     public String getPrintableSsid() {
1198         if (SSID == null) return "";
1199         final int length = SSID.length();
1200         if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') {
1201             return SSID.substring(1, length - 1);
1202         }
1203 
1204         /** The ascii-encoded string format is P"<ascii-encoded-string>"
1205          * The decoding is implemented in the supplicant for a newly configured
1206          * network.
1207          */
1208         if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') &&
1209                 (SSID.charAt(length-1) == '"')) {
1210             WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(
1211                     SSID.substring(2, length - 1));
1212             return wifiSsid.toString();
1213         }
1214         return SSID;
1215     }
1216 
1217     /** @hide **/
userApprovedAsString(int userApproved)1218     public static String userApprovedAsString(int userApproved) {
1219         switch (userApproved) {
1220             case USER_APPROVED:
1221                 return "USER_APPROVED";
1222             case USER_BANNED:
1223                 return "USER_BANNED";
1224             case USER_UNSPECIFIED:
1225                 return "USER_UNSPECIFIED";
1226             default:
1227                 return "INVALID";
1228         }
1229     }
1230 
1231     /**
1232      * Get an identifier for associating credentials with this config
1233      * @param current configuration contains values for additional fields
1234      *                that are not part of this configuration. Used
1235      *                when a config with some fields is passed by an application.
1236      * @throws IllegalStateException if config is invalid for key id generation
1237      * @hide
1238      */
getKeyIdForCredentials(WifiConfiguration current)1239     public String getKeyIdForCredentials(WifiConfiguration current) {
1240         String keyMgmt = null;
1241 
1242         try {
1243             // Get current config details for fields that are not initialized
1244             if (TextUtils.isEmpty(SSID)) SSID = current.SSID;
1245             if (allowedKeyManagement.cardinality() == 0) {
1246                 allowedKeyManagement = current.allowedKeyManagement;
1247             }
1248             if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
1249                 keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP];
1250             }
1251             if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
1252                 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X];
1253             }
1254 
1255             if (TextUtils.isEmpty(keyMgmt)) {
1256                 throw new IllegalStateException("Not an EAP network");
1257             }
1258 
1259             return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" +
1260                     trimStringForKeyId(enterpriseConfig.getKeyId(current != null ?
1261                             current.enterpriseConfig : null));
1262         } catch (NullPointerException e) {
1263             throw new IllegalStateException("Invalid config details");
1264         }
1265     }
1266 
trimStringForKeyId(String string)1267     private String trimStringForKeyId(String string) {
1268         // Remove quotes and spaces
1269         return string.replace("\"", "").replace(" ", "");
1270     }
1271 
readBitSet(Parcel src)1272     private static BitSet readBitSet(Parcel src) {
1273         int cardinality = src.readInt();
1274 
1275         BitSet set = new BitSet();
1276         for (int i = 0; i < cardinality; i++) {
1277             set.set(src.readInt());
1278         }
1279 
1280         return set;
1281     }
1282 
writeBitSet(Parcel dest, BitSet set)1283     private static void writeBitSet(Parcel dest, BitSet set) {
1284         int nextSetBit = -1;
1285 
1286         dest.writeInt(set.cardinality());
1287 
1288         while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
1289             dest.writeInt(nextSetBit);
1290         }
1291     }
1292 
1293     /** @hide */
getAuthType()1294     public int getAuthType() {
1295         if (allowedKeyManagement.cardinality() > 1) {
1296             throw new IllegalStateException("More than one auth type set");
1297         }
1298         if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
1299             return KeyMgmt.WPA_PSK;
1300         } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
1301             return KeyMgmt.WPA2_PSK;
1302         } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
1303             return KeyMgmt.WPA_EAP;
1304         } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
1305             return KeyMgmt.IEEE8021X;
1306         }
1307         return KeyMgmt.NONE;
1308     }
1309 
1310     /* @hide
1311      * Cache the config key, this seems useful as a speed up since a lot of
1312      * lookups in the config store are done and based on this key.
1313      */
1314     String mCachedConfigKey;
1315 
1316     /** @hide
1317      *  return the string used to calculate the hash in WifiConfigStore
1318      *  and uniquely identify this WifiConfiguration
1319      */
configKey(boolean allowCached)1320     public String configKey(boolean allowCached) {
1321         String key;
1322         if (allowCached && mCachedConfigKey != null) {
1323             key = mCachedConfigKey;
1324         } else if (providerFriendlyName != null) {
1325             key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP];
1326         } else {
1327             if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
1328                 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK];
1329             } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
1330                     allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
1331                 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];
1332             } else if (wepKeys[0] != null) {
1333                 key = SSID + "WEP";
1334             } else {
1335                 key = SSID + KeyMgmt.strings[KeyMgmt.NONE];
1336             }
1337             mCachedConfigKey = key;
1338         }
1339         return key;
1340     }
1341 
1342     /** @hide
1343      * get configKey, force calculating the config string
1344      */
configKey()1345     public String configKey() {
1346         return configKey(false);
1347     }
1348 
1349     /** @hide
1350      * return the config key string based on a scan result
1351      */
configKey(ScanResult result)1352     static public String configKey(ScanResult result) {
1353         String key = "\"" + result.SSID + "\"";
1354 
1355         if (result.capabilities.contains("WEP")) {
1356             key = key + "-WEP";
1357         }
1358 
1359         if (result.capabilities.contains("PSK")) {
1360             key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_PSK];
1361         }
1362 
1363         if (result.capabilities.contains("EAP")) {
1364             key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_EAP];
1365         }
1366 
1367         return key;
1368     }
1369 
1370     /** @hide */
getIpConfiguration()1371     public IpConfiguration getIpConfiguration() {
1372         return mIpConfiguration;
1373     }
1374 
1375     /** @hide */
setIpConfiguration(IpConfiguration ipConfiguration)1376     public void setIpConfiguration(IpConfiguration ipConfiguration) {
1377         mIpConfiguration = ipConfiguration;
1378     }
1379 
1380     /** @hide */
getStaticIpConfiguration()1381     public StaticIpConfiguration getStaticIpConfiguration() {
1382         return mIpConfiguration.getStaticIpConfiguration();
1383     }
1384 
1385     /** @hide */
setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration)1386     public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
1387         mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration);
1388     }
1389 
1390     /** @hide */
getIpAssignment()1391     public IpConfiguration.IpAssignment getIpAssignment() {
1392         return mIpConfiguration.ipAssignment;
1393     }
1394 
1395     /** @hide */
setIpAssignment(IpConfiguration.IpAssignment ipAssignment)1396     public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) {
1397         mIpConfiguration.ipAssignment = ipAssignment;
1398     }
1399 
1400     /** @hide */
getProxySettings()1401     public IpConfiguration.ProxySettings getProxySettings() {
1402         return mIpConfiguration.proxySettings;
1403     }
1404 
1405     /** @hide */
setProxySettings(IpConfiguration.ProxySettings proxySettings)1406     public void setProxySettings(IpConfiguration.ProxySettings proxySettings) {
1407         mIpConfiguration.proxySettings = proxySettings;
1408     }
1409 
1410     /** @hide */
getHttpProxy()1411     public ProxyInfo getHttpProxy() {
1412         return mIpConfiguration.httpProxy;
1413     }
1414 
1415     /** @hide */
setHttpProxy(ProxyInfo httpProxy)1416     public void setHttpProxy(ProxyInfo httpProxy) {
1417         mIpConfiguration.httpProxy = httpProxy;
1418     }
1419 
1420     /** @hide */
setProxy(ProxySettings settings, ProxyInfo proxy)1421     public void setProxy(ProxySettings settings, ProxyInfo proxy) {
1422         mIpConfiguration.proxySettings = settings;
1423         mIpConfiguration.httpProxy = proxy;
1424     }
1425 
1426     /** Implement the Parcelable interface {@hide} */
describeContents()1427     public int describeContents() {
1428         return 0;
1429     }
1430 
1431     /** copy constructor {@hide} */
WifiConfiguration(WifiConfiguration source)1432     public WifiConfiguration(WifiConfiguration source) {
1433         if (source != null) {
1434             networkId = source.networkId;
1435             status = source.status;
1436             disableReason = source.disableReason;
1437             disableReason = source.disableReason;
1438             SSID = source.SSID;
1439             BSSID = source.BSSID;
1440             FQDN = source.FQDN;
1441             roamingConsortiumIds = source.roamingConsortiumIds.clone();
1442             providerFriendlyName = source.providerFriendlyName;
1443             preSharedKey = source.preSharedKey;
1444 
1445             apBand = source.apBand;
1446             apChannel = source.apChannel;
1447 
1448             wepKeys = new String[4];
1449             for (int i = 0; i < wepKeys.length; i++) {
1450                 wepKeys[i] = source.wepKeys[i];
1451             }
1452 
1453             wepTxKeyIndex = source.wepTxKeyIndex;
1454             priority = source.priority;
1455             hiddenSSID = source.hiddenSSID;
1456             allowedKeyManagement   = (BitSet) source.allowedKeyManagement.clone();
1457             allowedProtocols       = (BitSet) source.allowedProtocols.clone();
1458             allowedAuthAlgorithms  = (BitSet) source.allowedAuthAlgorithms.clone();
1459             allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone();
1460             allowedGroupCiphers    = (BitSet) source.allowedGroupCiphers.clone();
1461 
1462             enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
1463 
1464             defaultGwMacAddress = source.defaultGwMacAddress;
1465 
1466             mIpConfiguration = new IpConfiguration(source.mIpConfiguration);
1467 
1468             if ((source.connectChoices != null) && (source.connectChoices.size() > 0)) {
1469                 connectChoices = new HashMap<String, Integer>();
1470                 connectChoices.putAll(source.connectChoices);
1471             }
1472 
1473             if ((source.linkedConfigurations != null)
1474                     && (source.linkedConfigurations.size() > 0)) {
1475                 linkedConfigurations = new HashMap<String, Integer>();
1476                 linkedConfigurations.putAll(source.linkedConfigurations);
1477             }
1478             mCachedConfigKey = null; //force null configKey
1479             autoJoinStatus = source.autoJoinStatus;
1480             selfAdded = source.selfAdded;
1481             validatedInternetAccess = source.validatedInternetAccess;
1482             ephemeral = source.ephemeral;
1483             if (source.visibility != null) {
1484                 visibility = new Visibility(source.visibility);
1485             }
1486 
1487             lastFailure = source.lastFailure;
1488             didSelfAdd = source.didSelfAdd;
1489             lastConnectUid = source.lastConnectUid;
1490             lastUpdateUid = source.lastUpdateUid;
1491             creatorUid = source.creatorUid;
1492             creatorName = source.creatorName;
1493             lastUpdateName = source.lastUpdateName;
1494             peerWifiConfiguration = source.peerWifiConfiguration;
1495             blackListTimestamp = source.blackListTimestamp;
1496             lastConnected = source.lastConnected;
1497             lastDisconnected = source.lastDisconnected;
1498             lastConnectionFailure = source.lastConnectionFailure;
1499             lastRoamingFailure = source.lastRoamingFailure;
1500             lastRoamingFailureReason = source.lastRoamingFailureReason;
1501             roamingFailureBlackListTimeMilli = source.roamingFailureBlackListTimeMilli;
1502             numConnectionFailures = source.numConnectionFailures;
1503             numIpConfigFailures = source.numIpConfigFailures;
1504             numAuthFailures = source.numAuthFailures;
1505             numScorerOverride = source.numScorerOverride;
1506             numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
1507             numAssociation = source.numAssociation;
1508             numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI;
1509             numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI;
1510             numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI;
1511             numTicksAtLowRSSI = source.numTicksAtLowRSSI;
1512             numTicksAtBadRSSI = source.numTicksAtBadRSSI;
1513             numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI;
1514             numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts;
1515             autoJoinBSSID = source.autoJoinBSSID;
1516             autoJoinUseAggressiveJoinAttemptThreshold
1517                     = source.autoJoinUseAggressiveJoinAttemptThreshold;
1518             autoJoinBailedDueToLowRssi = source.autoJoinBailedDueToLowRssi;
1519             dirty = source.dirty;
1520             userApproved = source.userApproved;
1521             numNoInternetAccessReports = source.numNoInternetAccessReports;
1522             noInternetAccessExpected = source.noInternetAccessExpected;
1523             creationTime = source.creationTime;
1524             updateTime = source.updateTime;
1525         }
1526     }
1527 
1528     /** {@hide} */
1529     //public static final int NOTHING_TAG = 0;
1530     /** {@hide} */
1531     //public static final int SCAN_CACHE_TAG = 1;
1532 
1533     /** Implement the Parcelable interface {@hide} */
1534     @Override
writeToParcel(Parcel dest, int flags)1535     public void writeToParcel(Parcel dest, int flags) {
1536         dest.writeInt(networkId);
1537         dest.writeInt(status);
1538         dest.writeInt(disableReason);
1539         dest.writeString(SSID);
1540         dest.writeString(BSSID);
1541         dest.writeInt(apBand);
1542         dest.writeInt(apChannel);
1543         dest.writeString(autoJoinBSSID);
1544         dest.writeString(FQDN);
1545         dest.writeString(providerFriendlyName);
1546         dest.writeInt(roamingConsortiumIds.length);
1547         for (long roamingConsortiumId : roamingConsortiumIds) {
1548             dest.writeLong(roamingConsortiumId);
1549         }
1550         dest.writeString(preSharedKey);
1551         for (String wepKey : wepKeys) {
1552             dest.writeString(wepKey);
1553         }
1554         dest.writeInt(wepTxKeyIndex);
1555         dest.writeInt(priority);
1556         dest.writeInt(hiddenSSID ? 1 : 0);
1557         dest.writeInt(requirePMF ? 1 : 0);
1558         dest.writeString(updateIdentifier);
1559 
1560         writeBitSet(dest, allowedKeyManagement);
1561         writeBitSet(dest, allowedProtocols);
1562         writeBitSet(dest, allowedAuthAlgorithms);
1563         writeBitSet(dest, allowedPairwiseCiphers);
1564         writeBitSet(dest, allowedGroupCiphers);
1565 
1566         dest.writeParcelable(enterpriseConfig, flags);
1567 
1568         dest.writeParcelable(mIpConfiguration, flags);
1569         dest.writeString(dhcpServer);
1570         dest.writeString(defaultGwMacAddress);
1571         dest.writeInt(autoJoinStatus);
1572         dest.writeInt(selfAdded ? 1 : 0);
1573         dest.writeInt(didSelfAdd ? 1 : 0);
1574         dest.writeInt(validatedInternetAccess ? 1 : 0);
1575         dest.writeInt(ephemeral ? 1 : 0);
1576         dest.writeInt(creatorUid);
1577         dest.writeInt(lastConnectUid);
1578         dest.writeInt(lastUpdateUid);
1579         dest.writeString(creatorName);
1580         dest.writeString(lastUpdateName);
1581         dest.writeLong(blackListTimestamp);
1582         dest.writeLong(lastConnectionFailure);
1583         dest.writeLong(lastRoamingFailure);
1584         dest.writeInt(lastRoamingFailureReason);
1585         dest.writeLong(roamingFailureBlackListTimeMilli);
1586         dest.writeInt(numConnectionFailures);
1587         dest.writeInt(numIpConfigFailures);
1588         dest.writeInt(numAuthFailures);
1589         dest.writeInt(numScorerOverride);
1590         dest.writeInt(numScorerOverrideAndSwitchedNetwork);
1591         dest.writeInt(numAssociation);
1592         dest.writeInt(numUserTriggeredWifiDisableLowRSSI);
1593         dest.writeInt(numUserTriggeredWifiDisableBadRSSI);
1594         dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI);
1595         dest.writeInt(numTicksAtLowRSSI);
1596         dest.writeInt(numTicksAtBadRSSI);
1597         dest.writeInt(numTicksAtNotHighRSSI);
1598         dest.writeInt(numUserTriggeredJoinAttempts);
1599         dest.writeInt(autoJoinUseAggressiveJoinAttemptThreshold);
1600         dest.writeInt(autoJoinBailedDueToLowRssi ? 1 : 0);
1601         dest.writeInt(userApproved);
1602         dest.writeInt(numNoInternetAccessReports);
1603         dest.writeInt(noInternetAccessExpected ? 1 : 0);
1604     }
1605 
1606     /** Implement the Parcelable interface {@hide} */
1607     public static final Creator<WifiConfiguration> CREATOR =
1608         new Creator<WifiConfiguration>() {
1609             public WifiConfiguration createFromParcel(Parcel in) {
1610                 WifiConfiguration config = new WifiConfiguration();
1611                 config.networkId = in.readInt();
1612                 config.status = in.readInt();
1613                 config.disableReason = in.readInt();
1614                 config.SSID = in.readString();
1615                 config.BSSID = in.readString();
1616                 config.apBand = in.readInt();
1617                 config.apChannel = in.readInt();
1618                 config.autoJoinBSSID = in.readString();
1619                 config.FQDN = in.readString();
1620                 config.providerFriendlyName = in.readString();
1621                 int numRoamingConsortiumIds = in.readInt();
1622                 config.roamingConsortiumIds = new long[numRoamingConsortiumIds];
1623                 for (int i = 0; i < numRoamingConsortiumIds; i++) {
1624                     config.roamingConsortiumIds[i] = in.readLong();
1625                 }
1626                 config.preSharedKey = in.readString();
1627                 for (int i = 0; i < config.wepKeys.length; i++) {
1628                     config.wepKeys[i] = in.readString();
1629                 }
1630                 config.wepTxKeyIndex = in.readInt();
1631                 config.priority = in.readInt();
1632                 config.hiddenSSID = in.readInt() != 0;
1633                 config.requirePMF = in.readInt() != 0;
1634                 config.updateIdentifier = in.readString();
1635 
1636                 config.allowedKeyManagement   = readBitSet(in);
1637                 config.allowedProtocols       = readBitSet(in);
1638                 config.allowedAuthAlgorithms  = readBitSet(in);
1639                 config.allowedPairwiseCiphers = readBitSet(in);
1640                 config.allowedGroupCiphers    = readBitSet(in);
1641 
1642                 config.enterpriseConfig = in.readParcelable(null);
1643 
1644                 config.mIpConfiguration = in.readParcelable(null);
1645                 config.dhcpServer = in.readString();
1646                 config.defaultGwMacAddress = in.readString();
1647                 config.autoJoinStatus = in.readInt();
1648                 config.selfAdded = in.readInt() != 0;
1649                 config.didSelfAdd = in.readInt() != 0;
1650                 config.validatedInternetAccess = in.readInt() != 0;
1651                 config.ephemeral = in.readInt() != 0;
1652                 config.creatorUid = in.readInt();
1653                 config.lastConnectUid = in.readInt();
1654                 config.lastUpdateUid = in.readInt();
1655                 config.creatorName = in.readString();
1656                 config.lastUpdateName = in.readString();
1657                 config.blackListTimestamp = in.readLong();
1658                 config.lastConnectionFailure = in.readLong();
1659                 config.lastRoamingFailure = in.readLong();
1660                 config.lastRoamingFailureReason = in.readInt();
1661                 config.roamingFailureBlackListTimeMilli = in.readLong();
1662                 config.numConnectionFailures = in.readInt();
1663                 config.numIpConfigFailures = in.readInt();
1664                 config.numAuthFailures = in.readInt();
1665                 config.numScorerOverride = in.readInt();
1666                 config.numScorerOverrideAndSwitchedNetwork = in.readInt();
1667                 config.numAssociation = in.readInt();
1668                 config.numUserTriggeredWifiDisableLowRSSI = in.readInt();
1669                 config.numUserTriggeredWifiDisableBadRSSI = in.readInt();
1670                 config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt();
1671                 config.numTicksAtLowRSSI = in.readInt();
1672                 config.numTicksAtBadRSSI = in.readInt();
1673                 config.numTicksAtNotHighRSSI = in.readInt();
1674                 config.numUserTriggeredJoinAttempts = in.readInt();
1675                 config.autoJoinUseAggressiveJoinAttemptThreshold = in.readInt();
1676                 config.autoJoinBailedDueToLowRssi = in.readInt() != 0;
1677                 config.userApproved = in.readInt();
1678                 config.numNoInternetAccessReports = in.readInt();
1679                 config.noInternetAccessExpected = in.readInt() != 0;
1680                 return config;
1681             }
1682 
1683             public WifiConfiguration[] newArray(int size) {
1684                 return new WifiConfiguration[size];
1685             }
1686         };
1687 }
1688