Home | History | Annotate | Download | only in wifi
      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.net.LinkProperties;
     20 import android.os.Parcelable;
     21 import android.os.Parcel;
     22 import android.text.TextUtils;
     23 
     24 import java.util.BitSet;
     25 
     26 /**
     27  * A class representing a configured Wi-Fi network, including the
     28  * security configuration.
     29  */
     30 public class WifiConfiguration implements Parcelable {
     31     private static final String TAG = "WifiConfiguration";
     32     /** {@hide} */
     33     public static final String ssidVarName = "ssid";
     34     /** {@hide} */
     35     public static final String bssidVarName = "bssid";
     36     /** {@hide} */
     37     public static final String pskVarName = "psk";
     38     /** {@hide} */
     39     public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" };
     40     /** {@hide} */
     41     public static final String wepTxKeyIdxVarName = "wep_tx_keyidx";
     42     /** {@hide} */
     43     public static final String priorityVarName = "priority";
     44     /** {@hide} */
     45     public static final String hiddenSSIDVarName = "scan_ssid";
     46     /** {@hide} */
     47     public static final int INVALID_NETWORK_ID = -1;
     48     /**
     49      * Recognized key management schemes.
     50      */
     51     public static class KeyMgmt {
     52         private KeyMgmt() { }
     53 
     54         /** WPA is not used; plaintext or static WEP could be used. */
     55         public static final int NONE = 0;
     56         /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */
     57         public static final int WPA_PSK = 1;
     58         /** WPA using EAP authentication. Generally used with an external authentication server. */
     59         public static final int WPA_EAP = 2;
     60         /** IEEE 802.1X using EAP authentication and (optionally) dynamically
     61          * generated WEP keys. */
     62         public static final int IEEE8021X = 3;
     63 
     64         /** WPA2 pre-shared key for use with soft access point
     65           * (requires {@code preSharedKey} to be specified).
     66           * @hide
     67           */
     68         public static final int WPA2_PSK = 4;
     69 
     70         public static final String varName = "key_mgmt";
     71 
     72         public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X",
     73                 "WPA2_PSK" };
     74     }
     75 
     76     /**
     77      * Recognized security protocols.
     78      */
     79     public static class Protocol {
     80         private Protocol() { }
     81 
     82         /** WPA/IEEE 802.11i/D3.0 */
     83         public static final int WPA = 0;
     84         /** WPA2/IEEE 802.11i */
     85         public static final int RSN = 1;
     86 
     87         public static final String varName = "proto";
     88 
     89         public static final String[] strings = { "WPA", "RSN" };
     90     }
     91 
     92     /**
     93      * Recognized IEEE 802.11 authentication algorithms.
     94      */
     95     public static class AuthAlgorithm {
     96         private AuthAlgorithm() { }
     97 
     98         /** Open System authentication (required for WPA/WPA2) */
     99         public static final int OPEN = 0;
    100         /** Shared Key authentication (requires static WEP keys) */
    101         public static final int SHARED = 1;
    102         /** LEAP/Network EAP (only used with LEAP) */
    103         public static final int LEAP = 2;
    104 
    105         public static final String varName = "auth_alg";
    106 
    107         public static final String[] strings = { "OPEN", "SHARED", "LEAP" };
    108     }
    109 
    110     /**
    111      * Recognized pairwise ciphers for WPA.
    112      */
    113     public static class PairwiseCipher {
    114         private PairwiseCipher() { }
    115 
    116         /** Use only Group keys (deprecated) */
    117         public static final int NONE = 0;
    118         /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
    119         public static final int TKIP = 1;
    120         /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
    121         public static final int CCMP = 2;
    122 
    123         public static final String varName = "pairwise";
    124 
    125         public static final String[] strings = { "NONE", "TKIP", "CCMP" };
    126     }
    127 
    128     /**
    129      * Recognized group ciphers.
    130      * <pre>
    131      * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
    132      * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
    133      * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
    134      * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
    135      * </pre>
    136      */
    137     public static class GroupCipher {
    138         private GroupCipher() { }
    139 
    140         /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */
    141         public static final int WEP40 = 0;
    142         /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */
    143         public static final int WEP104 = 1;
    144         /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
    145         public static final int TKIP = 2;
    146         /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
    147         public static final int CCMP = 3;
    148 
    149         public static final String varName = "group";
    150 
    151         public static final String[] strings = { "WEP40", "WEP104", "TKIP", "CCMP" };
    152     }
    153 
    154     /** Possible status of a network configuration. */
    155     public static class Status {
    156         private Status() { }
    157 
    158         /** this is the network we are currently connected to */
    159         public static final int CURRENT = 0;
    160         /** supplicant will not attempt to use this network */
    161         public static final int DISABLED = 1;
    162         /** supplicant will consider this network available for association */
    163         public static final int ENABLED = 2;
    164 
    165         public static final String[] strings = { "current", "disabled", "enabled" };
    166     }
    167 
    168     /** @hide */
    169     public static final int DISABLED_UNKNOWN_REASON                         = 0;
    170     /** @hide */
    171     public static final int DISABLED_DNS_FAILURE                            = 1;
    172     /** @hide */
    173     public static final int DISABLED_DHCP_FAILURE                           = 2;
    174     /** @hide */
    175     public static final int DISABLED_AUTH_FAILURE                           = 3;
    176     /** @hide */
    177     public static final int DISABLED_ASSOCIATION_REJECT                     = 4;
    178 
    179     /**
    180      * The ID number that the supplicant uses to identify this
    181      * network configuration entry. This must be passed as an argument
    182      * to most calls into the supplicant.
    183      */
    184     public int networkId;
    185 
    186     /**
    187      * The current status of this network configuration entry.
    188      * @see Status
    189      */
    190     public int status;
    191 
    192     /**
    193      * The code referring to a reason for disabling the network
    194      * Valid when {@link #status} == Status.DISABLED
    195      * @hide
    196      */
    197     public int disableReason;
    198 
    199     /**
    200      * The network's SSID. Can either be an ASCII string,
    201      * which must be enclosed in double quotation marks
    202      * (e.g., {@code "MyNetwork"}, or a string of
    203      * hex digits,which are not enclosed in quotes
    204      * (e.g., {@code 01a243f405}).
    205      */
    206     public String SSID;
    207     /**
    208      * When set, this network configuration entry should only be used when
    209      * associating with the AP having the specified BSSID. The value is
    210      * a string in the format of an Ethernet MAC address, e.g.,
    211      * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
    212      */
    213     public String BSSID;
    214 
    215     /**
    216      * Pre-shared key for use with WPA-PSK.
    217      * <p/>
    218      * When the value of this key is read, the actual key is
    219      * not returned, just a "*" if the key has a value, or the null
    220      * string otherwise.
    221      */
    222     public String preSharedKey;
    223     /**
    224      * Up to four WEP keys. Either an ASCII string enclosed in double
    225      * quotation marks (e.g., {@code "abcdef"} or a string
    226      * of hex digits (e.g., {@code 0102030405}).
    227      * <p/>
    228      * When the value of one of these keys is read, the actual key is
    229      * not returned, just a "*" if the key has a value, or the null
    230      * string otherwise.
    231      */
    232     public String[] wepKeys;
    233 
    234     /** Default WEP key index, ranging from 0 to 3. */
    235     public int wepTxKeyIndex;
    236 
    237     /**
    238      * Priority determines the preference given to a network by {@code wpa_supplicant}
    239      * when choosing an access point with which to associate.
    240      */
    241     public int priority;
    242 
    243     /**
    244      * This is a network that does not broadcast its SSID, so an
    245      * SSID-specific probe request must be used for scans.
    246      */
    247     public boolean hiddenSSID;
    248 
    249     /**
    250      * The set of key management protocols supported by this configuration.
    251      * See {@link KeyMgmt} for descriptions of the values.
    252      * Defaults to WPA-PSK WPA-EAP.
    253      */
    254     public BitSet allowedKeyManagement;
    255     /**
    256      * The set of security protocols supported by this configuration.
    257      * See {@link Protocol} for descriptions of the values.
    258      * Defaults to WPA RSN.
    259      */
    260     public BitSet allowedProtocols;
    261     /**
    262      * The set of authentication protocols supported by this configuration.
    263      * See {@link AuthAlgorithm} for descriptions of the values.
    264      * Defaults to automatic selection.
    265      */
    266     public BitSet allowedAuthAlgorithms;
    267     /**
    268      * The set of pairwise ciphers for WPA supported by this configuration.
    269      * See {@link PairwiseCipher} for descriptions of the values.
    270      * Defaults to CCMP TKIP.
    271      */
    272     public BitSet allowedPairwiseCiphers;
    273     /**
    274      * The set of group ciphers supported by this configuration.
    275      * See {@link GroupCipher} for descriptions of the values.
    276      * Defaults to CCMP TKIP WEP104 WEP40.
    277      */
    278     public BitSet allowedGroupCiphers;
    279     /**
    280      * The enterprise configuration details specifying the EAP method,
    281      * certificates and other settings associated with the EAP.
    282      */
    283     public WifiEnterpriseConfig enterpriseConfig;
    284 
    285     /**
    286      * @hide
    287      */
    288     public enum IpAssignment {
    289         /* Use statically configured IP settings. Configuration can be accessed
    290          * with linkProperties */
    291         STATIC,
    292         /* Use dynamically configured IP settigns */
    293         DHCP,
    294         /* no IP details are assigned, this is used to indicate
    295          * that any existing IP settings should be retained */
    296         UNASSIGNED
    297     }
    298     /**
    299      * @hide
    300      */
    301     public IpAssignment ipAssignment;
    302 
    303     /**
    304      * @hide
    305      */
    306     public enum ProxySettings {
    307         /* No proxy is to be used. Any existing proxy settings
    308          * should be cleared. */
    309         NONE,
    310         /* Use statically configured proxy. Configuration can be accessed
    311          * with linkProperties */
    312         STATIC,
    313         /* no proxy details are assigned, this is used to indicate
    314          * that any existing proxy settings should be retained */
    315         UNASSIGNED,
    316         /* Use a Pac based proxy.
    317          */
    318         PAC
    319     }
    320     /**
    321      * @hide
    322      */
    323     public ProxySettings proxySettings;
    324     /**
    325      * @hide
    326      */
    327     public LinkProperties linkProperties;
    328 
    329     public WifiConfiguration() {
    330         networkId = INVALID_NETWORK_ID;
    331         SSID = null;
    332         BSSID = null;
    333         priority = 0;
    334         hiddenSSID = false;
    335         disableReason = DISABLED_UNKNOWN_REASON;
    336         allowedKeyManagement = new BitSet();
    337         allowedProtocols = new BitSet();
    338         allowedAuthAlgorithms = new BitSet();
    339         allowedPairwiseCiphers = new BitSet();
    340         allowedGroupCiphers = new BitSet();
    341         wepKeys = new String[4];
    342         for (int i = 0; i < wepKeys.length; i++) {
    343             wepKeys[i] = null;
    344         }
    345         enterpriseConfig = new WifiEnterpriseConfig();
    346         ipAssignment = IpAssignment.UNASSIGNED;
    347         proxySettings = ProxySettings.UNASSIGNED;
    348         linkProperties = new LinkProperties();
    349     }
    350 
    351     /**
    352      * indicates whether the configuration is valid
    353      * @return true if valid, false otherwise
    354      * @hide
    355      */
    356     public boolean isValid() {
    357         if (allowedKeyManagement.cardinality() > 1) {
    358             if (allowedKeyManagement.cardinality() != 2) {
    359                 return false;
    360             }
    361             if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) == false) {
    362                 return false;
    363             }
    364             if ((allowedKeyManagement.get(KeyMgmt.IEEE8021X) == false)
    365                     && (allowedKeyManagement.get(KeyMgmt.WPA_PSK) == false)) {
    366                 return false;
    367             }
    368         }
    369 
    370         // TODO: Add more checks
    371         return true;
    372     }
    373 
    374     @Override
    375     public String toString() {
    376         StringBuilder sbuf = new StringBuilder();
    377         if (this.status == WifiConfiguration.Status.CURRENT) {
    378             sbuf.append("* ");
    379         } else if (this.status == WifiConfiguration.Status.DISABLED) {
    380             sbuf.append("- DSBLE: ").append(this.disableReason).append(" ");
    381         }
    382         sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
    383                 append(" BSSID: ").append(this.BSSID).append(" PRIO: ").append(this.priority).
    384                 append('\n');
    385         sbuf.append(" KeyMgmt:");
    386         for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
    387             if (this.allowedKeyManagement.get(k)) {
    388                 sbuf.append(" ");
    389                 if (k < KeyMgmt.strings.length) {
    390                     sbuf.append(KeyMgmt.strings[k]);
    391                 } else {
    392                     sbuf.append("??");
    393                 }
    394             }
    395         }
    396         sbuf.append(" Protocols:");
    397         for (int p = 0; p < this.allowedProtocols.size(); p++) {
    398             if (this.allowedProtocols.get(p)) {
    399                 sbuf.append(" ");
    400                 if (p < Protocol.strings.length) {
    401                     sbuf.append(Protocol.strings[p]);
    402                 } else {
    403                     sbuf.append("??");
    404                 }
    405             }
    406         }
    407         sbuf.append('\n');
    408         sbuf.append(" AuthAlgorithms:");
    409         for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) {
    410             if (this.allowedAuthAlgorithms.get(a)) {
    411                 sbuf.append(" ");
    412                 if (a < AuthAlgorithm.strings.length) {
    413                     sbuf.append(AuthAlgorithm.strings[a]);
    414                 } else {
    415                     sbuf.append("??");
    416                 }
    417             }
    418         }
    419         sbuf.append('\n');
    420         sbuf.append(" PairwiseCiphers:");
    421         for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) {
    422             if (this.allowedPairwiseCiphers.get(pc)) {
    423                 sbuf.append(" ");
    424                 if (pc < PairwiseCipher.strings.length) {
    425                     sbuf.append(PairwiseCipher.strings[pc]);
    426                 } else {
    427                     sbuf.append("??");
    428                 }
    429             }
    430         }
    431         sbuf.append('\n');
    432         sbuf.append(" GroupCiphers:");
    433         for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) {
    434             if (this.allowedGroupCiphers.get(gc)) {
    435                 sbuf.append(" ");
    436                 if (gc < GroupCipher.strings.length) {
    437                     sbuf.append(GroupCipher.strings[gc]);
    438                 } else {
    439                     sbuf.append("??");
    440                 }
    441             }
    442         }
    443         sbuf.append('\n').append(" PSK: ");
    444         if (this.preSharedKey != null) {
    445             sbuf.append('*');
    446         }
    447 
    448         sbuf.append(enterpriseConfig);
    449         sbuf.append('\n');
    450 
    451         sbuf.append("IP assignment: " + ipAssignment.toString());
    452         sbuf.append("\n");
    453         sbuf.append("Proxy settings: " + proxySettings.toString());
    454         sbuf.append("\n");
    455         sbuf.append(linkProperties.toString());
    456         sbuf.append("\n");
    457 
    458         return sbuf.toString();
    459     }
    460 
    461     /**
    462      * Construct a WifiConfiguration from a scanned network
    463      * @param scannedAP the scan result used to construct the config entry
    464      * TODO: figure out whether this is a useful way to construct a new entry.
    465      *
    466     public WifiConfiguration(ScanResult scannedAP) {
    467         networkId = -1;
    468         SSID = scannedAP.SSID;
    469         BSSID = scannedAP.BSSID;
    470     }
    471     */
    472 
    473     /** {@hide} */
    474     public String getPrintableSsid() {
    475         if (SSID == null) return "";
    476         final int length = SSID.length();
    477         if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') {
    478             return SSID.substring(1, length - 1);
    479         }
    480 
    481         /** The ascii-encoded string format is P"<ascii-encoded-string>"
    482          * The decoding is implemented in the supplicant for a newly configured
    483          * network.
    484          */
    485         if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') &&
    486                 (SSID.charAt(length-1) == '"')) {
    487             WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(
    488                     SSID.substring(2, length - 1));
    489             return wifiSsid.toString();
    490         }
    491         return SSID;
    492     }
    493 
    494     /**
    495      * Get an identifier for associating credentials with this config
    496      * @param current configuration contains values for additional fields
    497      *                that are not part of this configuration. Used
    498      *                when a config with some fields is passed by an application.
    499      * @throws IllegalStateException if config is invalid for key id generation
    500      * @hide
    501      */
    502     String getKeyIdForCredentials(WifiConfiguration current) {
    503         String keyMgmt = null;
    504 
    505         try {
    506             // Get current config details for fields that are not initialized
    507             if (TextUtils.isEmpty(SSID)) SSID = current.SSID;
    508             if (allowedKeyManagement.cardinality() == 0) {
    509                 allowedKeyManagement = current.allowedKeyManagement;
    510             }
    511             if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
    512                 keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP];
    513             }
    514             if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
    515                 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X];
    516             }
    517 
    518             if (TextUtils.isEmpty(keyMgmt)) {
    519                 throw new IllegalStateException("Not an EAP network");
    520             }
    521 
    522             return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" +
    523                     trimStringForKeyId(enterpriseConfig.getKeyId(current != null ?
    524                             current.enterpriseConfig : null));
    525         } catch (NullPointerException e) {
    526             throw new IllegalStateException("Invalid config details");
    527         }
    528     }
    529 
    530     private String trimStringForKeyId(String string) {
    531         // Remove quotes and spaces
    532         return string.replace("\"", "").replace(" ", "");
    533     }
    534 
    535     private static BitSet readBitSet(Parcel src) {
    536         int cardinality = src.readInt();
    537 
    538         BitSet set = new BitSet();
    539         for (int i = 0; i < cardinality; i++) {
    540             set.set(src.readInt());
    541         }
    542 
    543         return set;
    544     }
    545 
    546     private static void writeBitSet(Parcel dest, BitSet set) {
    547         int nextSetBit = -1;
    548 
    549         dest.writeInt(set.cardinality());
    550 
    551         while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
    552             dest.writeInt(nextSetBit);
    553         }
    554     }
    555 
    556     /** @hide */
    557     public int getAuthType() {
    558         if (isValid() == false) {
    559             throw new IllegalStateException("Invalid configuration");
    560         }
    561         if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
    562             return KeyMgmt.WPA_PSK;
    563         } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
    564             return KeyMgmt.WPA2_PSK;
    565         } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
    566             return KeyMgmt.WPA_EAP;
    567         } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
    568             return KeyMgmt.IEEE8021X;
    569         }
    570         return KeyMgmt.NONE;
    571     }
    572 
    573     /** Implement the Parcelable interface {@hide} */
    574     public int describeContents() {
    575         return 0;
    576     }
    577 
    578     /** copy constructor {@hide} */
    579     public WifiConfiguration(WifiConfiguration source) {
    580         if (source != null) {
    581             networkId = source.networkId;
    582             status = source.status;
    583             disableReason = source.disableReason;
    584             SSID = source.SSID;
    585             BSSID = source.BSSID;
    586             preSharedKey = source.preSharedKey;
    587 
    588             wepKeys = new String[4];
    589             for (int i = 0; i < wepKeys.length; i++) {
    590                 wepKeys[i] = source.wepKeys[i];
    591             }
    592 
    593             wepTxKeyIndex = source.wepTxKeyIndex;
    594             priority = source.priority;
    595             hiddenSSID = source.hiddenSSID;
    596             allowedKeyManagement   = (BitSet) source.allowedKeyManagement.clone();
    597             allowedProtocols       = (BitSet) source.allowedProtocols.clone();
    598             allowedAuthAlgorithms  = (BitSet) source.allowedAuthAlgorithms.clone();
    599             allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone();
    600             allowedGroupCiphers    = (BitSet) source.allowedGroupCiphers.clone();
    601 
    602             enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
    603 
    604             ipAssignment = source.ipAssignment;
    605             proxySettings = source.proxySettings;
    606             linkProperties = new LinkProperties(source.linkProperties);
    607         }
    608     }
    609 
    610     /** Implement the Parcelable interface {@hide} */
    611     public void writeToParcel(Parcel dest, int flags) {
    612         dest.writeInt(networkId);
    613         dest.writeInt(status);
    614         dest.writeInt(disableReason);
    615         dest.writeString(SSID);
    616         dest.writeString(BSSID);
    617         dest.writeString(preSharedKey);
    618         for (String wepKey : wepKeys) {
    619             dest.writeString(wepKey);
    620         }
    621         dest.writeInt(wepTxKeyIndex);
    622         dest.writeInt(priority);
    623         dest.writeInt(hiddenSSID ? 1 : 0);
    624 
    625         writeBitSet(dest, allowedKeyManagement);
    626         writeBitSet(dest, allowedProtocols);
    627         writeBitSet(dest, allowedAuthAlgorithms);
    628         writeBitSet(dest, allowedPairwiseCiphers);
    629         writeBitSet(dest, allowedGroupCiphers);
    630 
    631         dest.writeParcelable(enterpriseConfig, flags);
    632 
    633         dest.writeString(ipAssignment.name());
    634         dest.writeString(proxySettings.name());
    635         dest.writeParcelable(linkProperties, flags);
    636     }
    637 
    638     /** Implement the Parcelable interface {@hide} */
    639     public static final Creator<WifiConfiguration> CREATOR =
    640         new Creator<WifiConfiguration>() {
    641             public WifiConfiguration createFromParcel(Parcel in) {
    642                 WifiConfiguration config = new WifiConfiguration();
    643                 config.networkId = in.readInt();
    644                 config.status = in.readInt();
    645                 config.disableReason = in.readInt();
    646                 config.SSID = in.readString();
    647                 config.BSSID = in.readString();
    648                 config.preSharedKey = in.readString();
    649                 for (int i = 0; i < config.wepKeys.length; i++) {
    650                     config.wepKeys[i] = in.readString();
    651                 }
    652                 config.wepTxKeyIndex = in.readInt();
    653                 config.priority = in.readInt();
    654                 config.hiddenSSID = in.readInt() != 0;
    655                 config.allowedKeyManagement   = readBitSet(in);
    656                 config.allowedProtocols       = readBitSet(in);
    657                 config.allowedAuthAlgorithms  = readBitSet(in);
    658                 config.allowedPairwiseCiphers = readBitSet(in);
    659                 config.allowedGroupCiphers    = readBitSet(in);
    660 
    661                 config.enterpriseConfig = in.readParcelable(null);
    662 
    663                 config.ipAssignment = IpAssignment.valueOf(in.readString());
    664                 config.proxySettings = ProxySettings.valueOf(in.readString());
    665                 config.linkProperties = in.readParcelable(null);
    666 
    667                 return config;
    668             }
    669 
    670             public WifiConfiguration[] newArray(int size) {
    671                 return new WifiConfiguration[size];
    672             }
    673         };
    674 }
    675