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