Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2016 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 com.android.server.wifi.util;
     18 
     19 import android.net.IpConfiguration;
     20 import android.net.IpConfiguration.IpAssignment;
     21 import android.net.IpConfiguration.ProxySettings;
     22 import android.net.LinkAddress;
     23 import android.net.NetworkUtils;
     24 import android.net.ProxyInfo;
     25 import android.net.RouteInfo;
     26 import android.net.StaticIpConfiguration;
     27 import android.net.wifi.WifiConfiguration;
     28 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
     29 import android.net.wifi.WifiEnterpriseConfig;
     30 import android.util.Log;
     31 import android.util.Pair;
     32 
     33 import com.android.internal.util.XmlUtils;
     34 
     35 import org.xmlpull.v1.XmlPullParser;
     36 import org.xmlpull.v1.XmlPullParserException;
     37 import org.xmlpull.v1.XmlSerializer;
     38 
     39 import java.io.IOException;
     40 import java.net.Inet4Address;
     41 import java.net.InetAddress;
     42 import java.util.Arrays;
     43 import java.util.BitSet;
     44 import java.util.HashMap;
     45 
     46 /**
     47  * Utils for manipulating XML data. This is essentially a wrapper over XmlUtils provided by core.
     48  * The utility provides methods to write/parse section headers and write/parse values.
     49  * This utility is designed for formatting the XML into the following format:
     50  * <Document Header>
     51  *  <Section 1 Header>
     52  *   <Value 1>
     53  *   <Value 2>
     54  *   ...
     55  *   <Sub Section 1 Header>
     56  *    <Value 1>
     57  *    <Value 2>
     58  *    ...
     59  *   </Sub Section 1 Header>
     60  *  </Section 1 Header>
     61  * </Document Header>
     62  *
     63  * Note: These utility methods are meant to be used for:
     64  * 1. Backup/restore wifi network data to/from cloud.
     65  * 2. Persisting wifi network data to/from disk.
     66  */
     67 public class XmlUtil {
     68     private static final String TAG = "WifiXmlUtil";
     69 
     70     /**
     71      * Ensure that the XML stream is at a start tag or the end of document.
     72      *
     73      * @throws XmlPullParserException if parsing errors occur.
     74      */
     75     private static void gotoStartTag(XmlPullParser in)
     76             throws XmlPullParserException, IOException {
     77         int type = in.getEventType();
     78         while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) {
     79             type = in.next();
     80         }
     81     }
     82 
     83     /**
     84      * Ensure that the XML stream is at an end tag or the end of document.
     85      *
     86      * @throws XmlPullParserException if parsing errors occur.
     87      */
     88     private static void gotoEndTag(XmlPullParser in)
     89             throws XmlPullParserException, IOException {
     90         int type = in.getEventType();
     91         while (type != XmlPullParser.END_TAG && type != XmlPullParser.END_DOCUMENT) {
     92             type = in.next();
     93         }
     94     }
     95 
     96     /**
     97      * Start processing the XML stream at the document header.
     98      *
     99      * @param in         XmlPullParser instance pointing to the XML stream.
    100      * @param headerName expected name for the start tag.
    101      * @throws XmlPullParserException if parsing errors occur.
    102      */
    103     public static void gotoDocumentStart(XmlPullParser in, String headerName)
    104             throws XmlPullParserException, IOException {
    105         XmlUtils.beginDocument(in, headerName);
    106     }
    107 
    108     /**
    109      * Move the XML stream to the next section header or indicate if there are no more sections.
    110      * The provided outerDepth is used to find sub sections within that depth.
    111      *
    112      * Use this to move across sections if the ordering of sections are variable. The returned name
    113      * can be used to decide what section is next.
    114      *
    115      * @param in         XmlPullParser instance pointing to the XML stream.
    116      * @param headerName An array of one string, used to return the name of the next section.
    117      * @param outerDepth Find section within this depth.
    118      * @return {@code true} if a next section is found, {@code false} if there are no more sections.
    119      * @throws XmlPullParserException if parsing errors occur.
    120      */
    121     public static boolean gotoNextSectionOrEnd(
    122             XmlPullParser in, String[] headerName, int outerDepth)
    123             throws XmlPullParserException, IOException {
    124         if (XmlUtils.nextElementWithin(in, outerDepth)) {
    125             headerName[0] = in.getName();
    126             return true;
    127         }
    128         return false;
    129     }
    130 
    131     /**
    132      * Move the XML stream to the next section header or indicate if there are no more sections.
    133      * If a section, exists ensure that the name matches the provided name.
    134      * The provided outerDepth is used to find sub sections within that depth.
    135      *
    136      * Use this to move across repeated sections until the end.
    137      *
    138      * @param in           XmlPullParser instance pointing to the XML stream.
    139      * @param expectedName expected name for the section header.
    140      * @param outerDepth   Find section within this depth.
    141      * @return {@code true} if a next section is found, {@code false} if there are no more sections.
    142      * @throws XmlPullParserException if the section header name does not match |expectedName|,
    143      *                                or if parsing errors occur.
    144      */
    145     public static boolean gotoNextSectionWithNameOrEnd(
    146             XmlPullParser in, String expectedName, int outerDepth)
    147             throws XmlPullParserException, IOException {
    148         String[] headerName = new String[1];
    149         if (gotoNextSectionOrEnd(in, headerName, outerDepth)) {
    150             if (headerName[0].equals(expectedName)) {
    151                 return true;
    152             }
    153             throw new XmlPullParserException(
    154                     "Next section name does not match expected name: " + expectedName);
    155         }
    156         return false;
    157     }
    158 
    159     /**
    160      * Move the XML stream to the next section header and ensure that the name matches the provided
    161      * name.
    162      * The provided outerDepth is used to find sub sections within that depth.
    163      *
    164      * Use this to move across sections if the ordering of sections are fixed.
    165      *
    166      * @param in           XmlPullParser instance pointing to the XML stream.
    167      * @param expectedName expected name for the section header.
    168      * @param outerDepth   Find section within this depth.
    169      * @throws XmlPullParserException if the section header name does not match |expectedName|,
    170      *                                there are no more sections or if parsing errors occur.
    171      */
    172     public static void gotoNextSectionWithName(
    173             XmlPullParser in, String expectedName, int outerDepth)
    174             throws XmlPullParserException, IOException {
    175         if (!gotoNextSectionWithNameOrEnd(in, expectedName, outerDepth)) {
    176             throw new XmlPullParserException("Section not found. Expected: " + expectedName);
    177         }
    178     }
    179 
    180     /**
    181      * Checks if the stream is at the end of a section of values. This moves the stream to next tag
    182      * and checks if it finds an end tag at the specified depth.
    183      *
    184      * @param in           XmlPullParser instance pointing to the XML stream.
    185      * @param sectionDepth depth of the start tag of this section. Used to match the end tag.
    186      * @return {@code true} if a end tag at the provided depth is found, {@code false} otherwise
    187      * @throws XmlPullParserException if parsing errors occur.
    188      */
    189     public static boolean isNextSectionEnd(XmlPullParser in, int sectionDepth)
    190             throws XmlPullParserException, IOException {
    191         return !XmlUtils.nextElementWithin(in, sectionDepth);
    192     }
    193 
    194     /**
    195      * Read the current value in the XML stream using core XmlUtils and stores the retrieved
    196      * value name in the string provided. This method reads the value contained in current start
    197      * tag.
    198      * Note: Because there could be genuine null values being read from the XML, this method raises
    199      * an exception to indicate errors.
    200      *
    201      * @param in        XmlPullParser instance pointing to the XML stream.
    202      * @param valueName An array of one string, used to return the name attribute
    203      *                  of the value's tag.
    204      * @return value retrieved from the XML stream.
    205      * @throws XmlPullParserException if parsing errors occur.
    206      */
    207     public static Object readCurrentValue(XmlPullParser in, String[] valueName)
    208             throws XmlPullParserException, IOException {
    209         Object value = XmlUtils.readValueXml(in, valueName);
    210         // XmlUtils.readValue does not always move the stream to the end of the tag. So, move
    211         // it to the end tag before returning from here.
    212         gotoEndTag(in);
    213         return value;
    214     }
    215 
    216     /**
    217      * Read the next value in the XML stream using core XmlUtils and ensure that it matches the
    218      * provided name. This method moves the stream to the next start tag and reads the value
    219      * contained in it.
    220      * Note: Because there could be genuine null values being read from the XML, this method raises
    221      * an exception to indicate errors.
    222      *
    223      * @param in XmlPullParser instance pointing to the XML stream.
    224      * @return value retrieved from the XML stream.
    225      * @throws XmlPullParserException if the value read does not match |expectedName|,
    226      *                                or if parsing errors occur.
    227      */
    228     public static Object readNextValueWithName(XmlPullParser in, String expectedName)
    229             throws XmlPullParserException, IOException {
    230         String[] valueName = new String[1];
    231         XmlUtils.nextElement(in);
    232         Object value = readCurrentValue(in, valueName);
    233         if (valueName[0].equals(expectedName)) {
    234             return value;
    235         }
    236         throw new XmlPullParserException(
    237                 "Value not found. Expected: " + expectedName + ", but got: " + valueName[0]);
    238     }
    239 
    240     /**
    241      * Write the XML document start with the provided document header name.
    242      *
    243      * @param out        XmlSerializer instance pointing to the XML stream.
    244      * @param headerName name for the start tag.
    245      */
    246     public static void writeDocumentStart(XmlSerializer out, String headerName)
    247             throws IOException {
    248         out.startDocument(null, true);
    249         out.startTag(null, headerName);
    250     }
    251 
    252     /**
    253      * Write the XML document end with the provided document header name.
    254      *
    255      * @param out        XmlSerializer instance pointing to the XML stream.
    256      * @param headerName name for the end tag.
    257      */
    258     public static void writeDocumentEnd(XmlSerializer out, String headerName)
    259             throws IOException {
    260         out.endTag(null, headerName);
    261         out.endDocument();
    262     }
    263 
    264     /**
    265      * Write a section start header tag with the provided section name.
    266      *
    267      * @param out        XmlSerializer instance pointing to the XML stream.
    268      * @param headerName name for the start tag.
    269      */
    270     public static void writeNextSectionStart(XmlSerializer out, String headerName)
    271             throws IOException {
    272         out.startTag(null, headerName);
    273     }
    274 
    275     /**
    276      * Write a section end header tag with the provided section name.
    277      *
    278      * @param out        XmlSerializer instance pointing to the XML stream.
    279      * @param headerName name for the end tag.
    280      */
    281     public static void writeNextSectionEnd(XmlSerializer out, String headerName)
    282             throws IOException {
    283         out.endTag(null, headerName);
    284     }
    285 
    286     /**
    287      * Write the value with the provided name in the XML stream using core XmlUtils.
    288      *
    289      * @param out   XmlSerializer instance pointing to the XML stream.
    290      * @param name  name of the value.
    291      * @param value value to be written.
    292      */
    293     public static void writeNextValue(XmlSerializer out, String name, Object value)
    294             throws XmlPullParserException, IOException {
    295         XmlUtils.writeValueXml(value, name, out);
    296     }
    297 
    298     /**
    299      * Utility class to serialize and deseriaize {@link WifiConfiguration} object to XML &
    300      * vice versa.
    301      * This is used by both {@link com.android.server.wifi.WifiConfigStore} &
    302      * {@link com.android.server.wifi.WifiBackupRestore} modules.
    303      * The |writeConfigurationToXml| has 2 versions, one for backup and one for config store.
    304      * There is only 1 version of |parseXmlToConfiguration| for both backup & config store.
    305      * The parse method is written so that any element added/deleted in future revisions can
    306      * be easily handled.
    307      */
    308     public static class WifiConfigurationXmlUtil {
    309         /**
    310          * List of XML tags corresponding to WifiConfiguration object elements.
    311          */
    312         public static final String XML_TAG_SSID = "SSID";
    313         public static final String XML_TAG_BSSID = "BSSID";
    314         public static final String XML_TAG_CONFIG_KEY = "ConfigKey";
    315         public static final String XML_TAG_PRE_SHARED_KEY = "PreSharedKey";
    316         public static final String XML_TAG_WEP_KEYS = "WEPKeys";
    317         public static final String XML_TAG_WEP_TX_KEY_INDEX = "WEPTxKeyIndex";
    318         public static final String XML_TAG_HIDDEN_SSID = "HiddenSSID";
    319         public static final String XML_TAG_REQUIRE_PMF = "RequirePMF";
    320         public static final String XML_TAG_ALLOWED_KEY_MGMT = "AllowedKeyMgmt";
    321         public static final String XML_TAG_ALLOWED_PROTOCOLS = "AllowedProtocols";
    322         public static final String XML_TAG_ALLOWED_AUTH_ALGOS = "AllowedAuthAlgos";
    323         public static final String XML_TAG_ALLOWED_GROUP_CIPHERS = "AllowedGroupCiphers";
    324         public static final String XML_TAG_ALLOWED_PAIRWISE_CIPHERS = "AllowedPairwiseCiphers";
    325         public static final String XML_TAG_SHARED = "Shared";
    326         public static final String XML_TAG_STATUS = "Status";
    327         public static final String XML_TAG_FQDN = "FQDN";
    328         public static final String XML_TAG_PROVIDER_FRIENDLY_NAME = "ProviderFriendlyName";
    329         public static final String XML_TAG_LINKED_NETWORKS_LIST = "LinkedNetworksList";
    330         public static final String XML_TAG_DEFAULT_GW_MAC_ADDRESS = "DefaultGwMacAddress";
    331         public static final String XML_TAG_VALIDATED_INTERNET_ACCESS = "ValidatedInternetAccess";
    332         public static final String XML_TAG_NO_INTERNET_ACCESS_EXPECTED = "NoInternetAccessExpected";
    333         public static final String XML_TAG_USER_APPROVED = "UserApproved";
    334         public static final String XML_TAG_METERED_HINT = "MeteredHint";
    335         public static final String XML_TAG_USE_EXTERNAL_SCORES = "UseExternalScores";
    336         public static final String XML_TAG_NUM_ASSOCIATION = "NumAssociation";
    337         public static final String XML_TAG_CREATOR_UID = "CreatorUid";
    338         public static final String XML_TAG_CREATOR_NAME = "CreatorName";
    339         public static final String XML_TAG_CREATION_TIME = "CreationTime";
    340         public static final String XML_TAG_LAST_UPDATE_UID = "LastUpdateUid";
    341         public static final String XML_TAG_LAST_UPDATE_NAME = "LastUpdateName";
    342         public static final String XML_TAG_LAST_CONNECT_UID = "LastConnectUid";
    343         public static final String XML_TAG_IS_LEGACY_PASSPOINT_CONFIG = "IsLegacyPasspointConfig";
    344         public static final String XML_TAG_ROAMING_CONSORTIUM_OIS = "RoamingConsortiumOIs";
    345 
    346         /**
    347          * Write WepKeys to the XML stream.
    348          * WepKeys array is intialized in WifiConfiguration constructor, but all of the elements
    349          * are set to null. User may chose to set any one of the key elements in WifiConfiguration.
    350          * XmlUtils serialization doesn't handle this array of nulls well .
    351          * So, write empty strings if some of the keys are not initialized and null if all of
    352          * the elements are empty.
    353          */
    354         private static void writeWepKeysToXml(XmlSerializer out, String[] wepKeys)
    355                 throws XmlPullParserException, IOException {
    356             String[] wepKeysToWrite = new String[wepKeys.length];
    357             boolean hasWepKey = false;
    358             for (int i = 0; i < wepKeys.length; i++) {
    359                 if (wepKeys[i] == null) {
    360                     wepKeysToWrite[i] = new String();
    361                 } else {
    362                     wepKeysToWrite[i] = wepKeys[i];
    363                     hasWepKey = true;
    364                 }
    365             }
    366             if (hasWepKey) {
    367                 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, wepKeysToWrite);
    368             } else {
    369                 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, null);
    370             }
    371         }
    372 
    373         /**
    374          * Write the Configuration data elements that are common for backup & config store to the
    375          * XML stream.
    376          *
    377          * @param out           XmlSerializer instance pointing to the XML stream.
    378          * @param configuration WifiConfiguration object to be serialized.
    379          */
    380         public static void writeCommonElementsToXml(
    381                 XmlSerializer out, WifiConfiguration configuration)
    382                 throws XmlPullParserException, IOException {
    383             XmlUtil.writeNextValue(out, XML_TAG_CONFIG_KEY, configuration.configKey());
    384             XmlUtil.writeNextValue(out, XML_TAG_SSID, configuration.SSID);
    385             XmlUtil.writeNextValue(out, XML_TAG_BSSID, configuration.BSSID);
    386             XmlUtil.writeNextValue(out, XML_TAG_PRE_SHARED_KEY, configuration.preSharedKey);
    387             writeWepKeysToXml(out, configuration.wepKeys);
    388             XmlUtil.writeNextValue(out, XML_TAG_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex);
    389             XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, configuration.hiddenSSID);
    390             XmlUtil.writeNextValue(out, XML_TAG_REQUIRE_PMF, configuration.requirePMF);
    391             XmlUtil.writeNextValue(
    392                     out, XML_TAG_ALLOWED_KEY_MGMT,
    393                     configuration.allowedKeyManagement.toByteArray());
    394             XmlUtil.writeNextValue(
    395                     out, XML_TAG_ALLOWED_PROTOCOLS,
    396                     configuration.allowedProtocols.toByteArray());
    397             XmlUtil.writeNextValue(
    398                     out, XML_TAG_ALLOWED_AUTH_ALGOS,
    399                     configuration.allowedAuthAlgorithms.toByteArray());
    400             XmlUtil.writeNextValue(
    401                     out, XML_TAG_ALLOWED_GROUP_CIPHERS,
    402                     configuration.allowedGroupCiphers.toByteArray());
    403             XmlUtil.writeNextValue(
    404                     out, XML_TAG_ALLOWED_PAIRWISE_CIPHERS,
    405                     configuration.allowedPairwiseCiphers.toByteArray());
    406             XmlUtil.writeNextValue(out, XML_TAG_SHARED, configuration.shared);
    407         }
    408 
    409         /**
    410          * Write the Configuration data elements for backup from the provided Configuration to the
    411          * XML stream.
    412          * Note: This is a subset of the elements serialized for config store.
    413          *
    414          * @param out           XmlSerializer instance pointing to the XML stream.
    415          * @param configuration WifiConfiguration object to be serialized.
    416          */
    417         public static void writeToXmlForBackup(XmlSerializer out, WifiConfiguration configuration)
    418                 throws XmlPullParserException, IOException {
    419             writeCommonElementsToXml(out, configuration);
    420         }
    421 
    422         /**
    423          * Write the Configuration data elements for config store from the provided Configuration
    424          * to the XML stream.
    425          *
    426          * @param out           XmlSerializer instance pointing to the XML stream.
    427          * @param configuration WifiConfiguration object to be serialized.
    428          */
    429         public static void writeToXmlForConfigStore(
    430                 XmlSerializer out, WifiConfiguration configuration)
    431                 throws XmlPullParserException, IOException {
    432             writeCommonElementsToXml(out, configuration);
    433             XmlUtil.writeNextValue(out, XML_TAG_STATUS, configuration.status);
    434             XmlUtil.writeNextValue(out, XML_TAG_FQDN, configuration.FQDN);
    435             XmlUtil.writeNextValue(
    436                     out, XML_TAG_PROVIDER_FRIENDLY_NAME, configuration.providerFriendlyName);
    437             XmlUtil.writeNextValue(
    438                     out, XML_TAG_LINKED_NETWORKS_LIST, configuration.linkedConfigurations);
    439             XmlUtil.writeNextValue(
    440                     out, XML_TAG_DEFAULT_GW_MAC_ADDRESS, configuration.defaultGwMacAddress);
    441             XmlUtil.writeNextValue(
    442                     out, XML_TAG_VALIDATED_INTERNET_ACCESS, configuration.validatedInternetAccess);
    443             XmlUtil.writeNextValue(
    444                     out, XML_TAG_NO_INTERNET_ACCESS_EXPECTED,
    445                     configuration.noInternetAccessExpected);
    446             XmlUtil.writeNextValue(out, XML_TAG_USER_APPROVED, configuration.userApproved);
    447             XmlUtil.writeNextValue(out, XML_TAG_METERED_HINT, configuration.meteredHint);
    448             XmlUtil.writeNextValue(
    449                     out, XML_TAG_USE_EXTERNAL_SCORES, configuration.useExternalScores);
    450             XmlUtil.writeNextValue(out, XML_TAG_NUM_ASSOCIATION, configuration.numAssociation);
    451             XmlUtil.writeNextValue(out, XML_TAG_CREATOR_UID, configuration.creatorUid);
    452             XmlUtil.writeNextValue(out, XML_TAG_CREATOR_NAME, configuration.creatorName);
    453             XmlUtil.writeNextValue(out, XML_TAG_CREATION_TIME, configuration.creationTime);
    454             XmlUtil.writeNextValue(out, XML_TAG_LAST_UPDATE_UID, configuration.lastUpdateUid);
    455             XmlUtil.writeNextValue(out, XML_TAG_LAST_UPDATE_NAME, configuration.lastUpdateName);
    456             XmlUtil.writeNextValue(out, XML_TAG_LAST_CONNECT_UID, configuration.lastConnectUid);
    457             XmlUtil.writeNextValue(
    458                     out, XML_TAG_IS_LEGACY_PASSPOINT_CONFIG,
    459                     configuration.isLegacyPasspointConfig);
    460             XmlUtil.writeNextValue(
    461                     out, XML_TAG_ROAMING_CONSORTIUM_OIS, configuration.roamingConsortiumIds);
    462         }
    463 
    464         /**
    465          * Populate wepKeys array elements only if they were non-empty in the backup data.
    466          *
    467          * @throws XmlPullParserException if parsing errors occur.
    468          */
    469         private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys)
    470                 throws XmlPullParserException, IOException {
    471             String[] wepKeysInData = (String[]) value;
    472             if (wepKeysInData == null) {
    473                 return;
    474             }
    475             if (wepKeysInData.length != wepKeys.length) {
    476                 throw new XmlPullParserException(
    477                         "Invalid Wep Keys length: " + wepKeysInData.length);
    478             }
    479             for (int i = 0; i < wepKeys.length; i++) {
    480                 if (wepKeysInData[i].isEmpty()) {
    481                     wepKeys[i] = null;
    482                 } else {
    483                     wepKeys[i] = wepKeysInData[i];
    484                 }
    485             }
    486         }
    487 
    488         /**
    489          * Parses the configuration data elements from the provided XML stream to a
    490          * WifiConfiguration object.
    491          * Note: This is used for parsing both backup data and config store data. Looping through
    492          * the tags make it easy to add or remove elements in the future versions if needed.
    493          *
    494          * @param in            XmlPullParser instance pointing to the XML stream.
    495          * @param outerTagDepth depth of the outer tag in the XML document.
    496          * @return Pair<Config key, WifiConfiguration object> if parsing is successful,
    497          * null otherwise.
    498          */
    499         public static Pair<String, WifiConfiguration> parseFromXml(
    500                 XmlPullParser in, int outerTagDepth)
    501                 throws XmlPullParserException, IOException {
    502             WifiConfiguration configuration = new WifiConfiguration();
    503             String configKeyInData = null;
    504 
    505             // Loop through and parse out all the elements from the stream within this section.
    506             while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
    507                 String[] valueName = new String[1];
    508                 Object value = XmlUtil.readCurrentValue(in, valueName);
    509                 if (valueName[0] == null) {
    510                     throw new XmlPullParserException("Missing value name");
    511                 }
    512                 switch (valueName[0]) {
    513                     case XML_TAG_CONFIG_KEY:
    514                         configKeyInData = (String) value;
    515                         break;
    516                     case XML_TAG_SSID:
    517                         configuration.SSID = (String) value;
    518                         break;
    519                     case XML_TAG_BSSID:
    520                         configuration.BSSID = (String) value;
    521                         break;
    522                     case XML_TAG_PRE_SHARED_KEY:
    523                         configuration.preSharedKey = (String) value;
    524                         break;
    525                     case XML_TAG_WEP_KEYS:
    526                         populateWepKeysFromXmlValue(value, configuration.wepKeys);
    527                         break;
    528                     case XML_TAG_WEP_TX_KEY_INDEX:
    529                         configuration.wepTxKeyIndex = (int) value;
    530                         break;
    531                     case XML_TAG_HIDDEN_SSID:
    532                         configuration.hiddenSSID = (boolean) value;
    533                         break;
    534                     case XML_TAG_REQUIRE_PMF:
    535                         configuration.requirePMF = (boolean) value;
    536                         break;
    537                     case XML_TAG_ALLOWED_KEY_MGMT:
    538                         byte[] allowedKeyMgmt = (byte[]) value;
    539                         configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt);
    540                         break;
    541                     case XML_TAG_ALLOWED_PROTOCOLS:
    542                         byte[] allowedProtocols = (byte[]) value;
    543                         configuration.allowedProtocols = BitSet.valueOf(allowedProtocols);
    544                         break;
    545                     case XML_TAG_ALLOWED_AUTH_ALGOS:
    546                         byte[] allowedAuthAlgorithms = (byte[]) value;
    547                         configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms);
    548                         break;
    549                     case XML_TAG_ALLOWED_GROUP_CIPHERS:
    550                         byte[] allowedGroupCiphers = (byte[]) value;
    551                         configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers);
    552                         break;
    553                     case XML_TAG_ALLOWED_PAIRWISE_CIPHERS:
    554                         byte[] allowedPairwiseCiphers = (byte[]) value;
    555                         configuration.allowedPairwiseCiphers =
    556                                 BitSet.valueOf(allowedPairwiseCiphers);
    557                         break;
    558                     case XML_TAG_SHARED:
    559                         configuration.shared = (boolean) value;
    560                         break;
    561                     case XML_TAG_STATUS:
    562                         int status = (int) value;
    563                         // Any network which was CURRENT before reboot needs
    564                         // to be restored to ENABLED.
    565                         if (status == WifiConfiguration.Status.CURRENT) {
    566                             status = WifiConfiguration.Status.ENABLED;
    567                         }
    568                         configuration.status = status;
    569                         break;
    570                     case XML_TAG_FQDN:
    571                         configuration.FQDN = (String) value;
    572                         break;
    573                     case XML_TAG_PROVIDER_FRIENDLY_NAME:
    574                         configuration.providerFriendlyName = (String) value;
    575                         break;
    576                     case XML_TAG_LINKED_NETWORKS_LIST:
    577                         configuration.linkedConfigurations = (HashMap<String, Integer>) value;
    578                         break;
    579                     case XML_TAG_DEFAULT_GW_MAC_ADDRESS:
    580                         configuration.defaultGwMacAddress = (String) value;
    581                         break;
    582                     case XML_TAG_VALIDATED_INTERNET_ACCESS:
    583                         configuration.validatedInternetAccess = (boolean) value;
    584                         break;
    585                     case XML_TAG_NO_INTERNET_ACCESS_EXPECTED:
    586                         configuration.noInternetAccessExpected = (boolean) value;
    587                         break;
    588                     case XML_TAG_USER_APPROVED:
    589                         configuration.userApproved = (int) value;
    590                         break;
    591                     case XML_TAG_METERED_HINT:
    592                         configuration.meteredHint = (boolean) value;
    593                         break;
    594                     case XML_TAG_USE_EXTERNAL_SCORES:
    595                         configuration.useExternalScores = (boolean) value;
    596                         break;
    597                     case XML_TAG_NUM_ASSOCIATION:
    598                         configuration.numAssociation = (int) value;
    599                         break;
    600                     case XML_TAG_CREATOR_UID:
    601                         configuration.creatorUid = (int) value;
    602                         break;
    603                     case XML_TAG_CREATOR_NAME:
    604                         configuration.creatorName = (String) value;
    605                         break;
    606                     case XML_TAG_CREATION_TIME:
    607                         configuration.creationTime = (String) value;
    608                         break;
    609                     case XML_TAG_LAST_UPDATE_UID:
    610                         configuration.lastUpdateUid = (int) value;
    611                         break;
    612                     case XML_TAG_LAST_UPDATE_NAME:
    613                         configuration.lastUpdateName = (String) value;
    614                         break;
    615                     case XML_TAG_LAST_CONNECT_UID:
    616                         configuration.lastConnectUid = (int) value;
    617                         break;
    618                     case XML_TAG_IS_LEGACY_PASSPOINT_CONFIG:
    619                         configuration.isLegacyPasspointConfig = (boolean) value;
    620                         break;
    621                     case XML_TAG_ROAMING_CONSORTIUM_OIS:
    622                         configuration.roamingConsortiumIds = (long[]) value;
    623                         break;
    624                     default:
    625                         throw new XmlPullParserException(
    626                                 "Unknown value name found: " + valueName[0]);
    627                 }
    628             }
    629             return Pair.create(configKeyInData, configuration);
    630         }
    631     }
    632 
    633     /**
    634      * Utility class to serialize and deseriaize {@link IpConfiguration} object to XML & vice versa.
    635      * This is used by both {@link com.android.server.wifi.WifiConfigStore} &
    636      * {@link com.android.server.wifi.WifiBackupRestore} modules.
    637      */
    638     public static class IpConfigurationXmlUtil {
    639 
    640         /**
    641          * List of XML tags corresponding to IpConfiguration object elements.
    642          */
    643         public static final String XML_TAG_IP_ASSIGNMENT = "IpAssignment";
    644         public static final String XML_TAG_LINK_ADDRESS = "LinkAddress";
    645         public static final String XML_TAG_LINK_PREFIX_LENGTH = "LinkPrefixLength";
    646         public static final String XML_TAG_GATEWAY_ADDRESS = "GatewayAddress";
    647         public static final String XML_TAG_DNS_SERVER_ADDRESSES = "DNSServers";
    648         public static final String XML_TAG_PROXY_SETTINGS = "ProxySettings";
    649         public static final String XML_TAG_PROXY_HOST = "ProxyHost";
    650         public static final String XML_TAG_PROXY_PORT = "ProxyPort";
    651         public static final String XML_TAG_PROXY_PAC_FILE = "ProxyPac";
    652         public static final String XML_TAG_PROXY_EXCLUSION_LIST = "ProxyExclusionList";
    653 
    654         /**
    655          * Write the static IP configuration data elements to XML stream.
    656          */
    657         private static void writeStaticIpConfigurationToXml(
    658                 XmlSerializer out, StaticIpConfiguration staticIpConfiguration)
    659                 throws XmlPullParserException, IOException {
    660             if (staticIpConfiguration.ipAddress != null) {
    661                 XmlUtil.writeNextValue(
    662                         out, XML_TAG_LINK_ADDRESS,
    663                         staticIpConfiguration.ipAddress.getAddress().getHostAddress());
    664                 XmlUtil.writeNextValue(
    665                         out, XML_TAG_LINK_PREFIX_LENGTH,
    666                         staticIpConfiguration.ipAddress.getPrefixLength());
    667             } else {
    668                 XmlUtil.writeNextValue(
    669                         out, XML_TAG_LINK_ADDRESS, null);
    670                 XmlUtil.writeNextValue(
    671                         out, XML_TAG_LINK_PREFIX_LENGTH, null);
    672             }
    673             if (staticIpConfiguration.gateway != null) {
    674                 XmlUtil.writeNextValue(
    675                         out, XML_TAG_GATEWAY_ADDRESS,
    676                         staticIpConfiguration.gateway.getHostAddress());
    677             } else {
    678                 XmlUtil.writeNextValue(
    679                         out, XML_TAG_GATEWAY_ADDRESS, null);
    680 
    681             }
    682             if (staticIpConfiguration.dnsServers != null) {
    683                 // Create a string array of DNS server addresses
    684                 String[] dnsServers = new String[staticIpConfiguration.dnsServers.size()];
    685                 int dnsServerIdx = 0;
    686                 for (InetAddress inetAddr : staticIpConfiguration.dnsServers) {
    687                     dnsServers[dnsServerIdx++] = inetAddr.getHostAddress();
    688                 }
    689                 XmlUtil.writeNextValue(
    690                         out, XML_TAG_DNS_SERVER_ADDRESSES, dnsServers);
    691             } else {
    692                 XmlUtil.writeNextValue(
    693                         out, XML_TAG_DNS_SERVER_ADDRESSES, null);
    694             }
    695         }
    696 
    697         /**
    698          * Write the IP configuration data elements from the provided Configuration to the XML
    699          * stream.
    700          *
    701          * @param out             XmlSerializer instance pointing to the XML stream.
    702          * @param ipConfiguration IpConfiguration object to be serialized.
    703          */
    704         public static void writeToXml(XmlSerializer out, IpConfiguration ipConfiguration)
    705                 throws XmlPullParserException, IOException {
    706             // Write IP assignment settings
    707             XmlUtil.writeNextValue(out, XML_TAG_IP_ASSIGNMENT,
    708                     ipConfiguration.ipAssignment.toString());
    709             switch (ipConfiguration.ipAssignment) {
    710                 case STATIC:
    711                     writeStaticIpConfigurationToXml(
    712                             out, ipConfiguration.getStaticIpConfiguration());
    713                     break;
    714                 default:
    715                     break;
    716             }
    717 
    718             // Write proxy settings
    719             XmlUtil.writeNextValue(
    720                     out, XML_TAG_PROXY_SETTINGS,
    721                     ipConfiguration.proxySettings.toString());
    722             switch (ipConfiguration.proxySettings) {
    723                 case STATIC:
    724                     XmlUtil.writeNextValue(
    725                             out, XML_TAG_PROXY_HOST,
    726                             ipConfiguration.httpProxy.getHost());
    727                     XmlUtil.writeNextValue(
    728                             out, XML_TAG_PROXY_PORT,
    729                             ipConfiguration.httpProxy.getPort());
    730                     XmlUtil.writeNextValue(
    731                             out, XML_TAG_PROXY_EXCLUSION_LIST,
    732                             ipConfiguration.httpProxy.getExclusionListAsString());
    733                     break;
    734                 case PAC:
    735                     XmlUtil.writeNextValue(
    736                             out, XML_TAG_PROXY_PAC_FILE,
    737                             ipConfiguration.httpProxy.getPacFileUrl().toString());
    738                     break;
    739                 default:
    740                     break;
    741             }
    742         }
    743 
    744         /**
    745          * Parse out the static IP configuration from the XML stream.
    746          */
    747         private static StaticIpConfiguration parseStaticIpConfigurationFromXml(XmlPullParser in)
    748                 throws XmlPullParserException, IOException {
    749             StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
    750 
    751             String linkAddressString =
    752                     (String) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_ADDRESS);
    753             Integer linkPrefixLength =
    754                     (Integer) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_PREFIX_LENGTH);
    755             if (linkAddressString != null && linkPrefixLength != null) {
    756                 LinkAddress linkAddress = new LinkAddress(
    757                         NetworkUtils.numericToInetAddress(linkAddressString),
    758                         linkPrefixLength);
    759                 if (linkAddress.getAddress() instanceof Inet4Address) {
    760                     staticIpConfiguration.ipAddress = linkAddress;
    761                 } else {
    762                     Log.w(TAG, "Non-IPv4 address: " + linkAddress);
    763                 }
    764             }
    765             String gatewayAddressString =
    766                     (String) XmlUtil.readNextValueWithName(in, XML_TAG_GATEWAY_ADDRESS);
    767             if (gatewayAddressString != null) {
    768                 LinkAddress dest = null;
    769                 InetAddress gateway =
    770                         NetworkUtils.numericToInetAddress(gatewayAddressString);
    771                 RouteInfo route = new RouteInfo(dest, gateway);
    772                 if (route.isIPv4Default()) {
    773                     staticIpConfiguration.gateway = gateway;
    774                 } else {
    775                     Log.w(TAG, "Non-IPv4 default route: " + route);
    776                 }
    777             }
    778             String[] dnsServerAddressesString =
    779                     (String[]) XmlUtil.readNextValueWithName(in, XML_TAG_DNS_SERVER_ADDRESSES);
    780             if (dnsServerAddressesString != null) {
    781                 for (String dnsServerAddressString : dnsServerAddressesString) {
    782                     InetAddress dnsServerAddress =
    783                             NetworkUtils.numericToInetAddress(dnsServerAddressString);
    784                     staticIpConfiguration.dnsServers.add(dnsServerAddress);
    785                 }
    786             }
    787             return staticIpConfiguration;
    788         }
    789 
    790         /**
    791          * Parses the IP configuration data elements from the provided XML stream to an
    792          * IpConfiguration object.
    793          *
    794          * @param in            XmlPullParser instance pointing to the XML stream.
    795          * @param outerTagDepth depth of the outer tag in the XML document.
    796          * @return IpConfiguration object if parsing is successful, null otherwise.
    797          */
    798         public static IpConfiguration parseFromXml(XmlPullParser in, int outerTagDepth)
    799                 throws XmlPullParserException, IOException {
    800             IpConfiguration ipConfiguration = new IpConfiguration();
    801 
    802             // Parse out the IP assignment info first.
    803             String ipAssignmentString =
    804                     (String) XmlUtil.readNextValueWithName(in, XML_TAG_IP_ASSIGNMENT);
    805             IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString);
    806             ipConfiguration.setIpAssignment(ipAssignment);
    807             switch (ipAssignment) {
    808                 case STATIC:
    809                     ipConfiguration.setStaticIpConfiguration(parseStaticIpConfigurationFromXml(in));
    810                     break;
    811                 case DHCP:
    812                 case UNASSIGNED:
    813                     break;
    814                 default:
    815                     throw new XmlPullParserException("Unknown ip assignment type: " + ipAssignment);
    816             }
    817 
    818             // Parse out the proxy settings next.
    819             String proxySettingsString =
    820                     (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_SETTINGS);
    821             ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString);
    822             ipConfiguration.setProxySettings(proxySettings);
    823             switch (proxySettings) {
    824                 case STATIC:
    825                     String proxyHost =
    826                             (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_HOST);
    827                     int proxyPort =
    828                             (int) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PORT);
    829                     String proxyExclusionList =
    830                             (String) XmlUtil.readNextValueWithName(
    831                                     in, XML_TAG_PROXY_EXCLUSION_LIST);
    832                     ipConfiguration.setHttpProxy(
    833                             new ProxyInfo(proxyHost, proxyPort, proxyExclusionList));
    834                     break;
    835                 case PAC:
    836                     String proxyPacFile =
    837                             (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PAC_FILE);
    838                     ipConfiguration.setHttpProxy(new ProxyInfo(proxyPacFile));
    839                     break;
    840                 case NONE:
    841                 case UNASSIGNED:
    842                     break;
    843                 default:
    844                     throw new XmlPullParserException(
    845                             "Unknown proxy settings type: " + proxySettings);
    846             }
    847             return ipConfiguration;
    848         }
    849     }
    850 
    851     /**
    852      * Utility class to serialize and deseriaize {@link NetworkSelectionStatus} object to XML &
    853      * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module.
    854      */
    855     public static class NetworkSelectionStatusXmlUtil {
    856 
    857         /**
    858          * List of XML tags corresponding to NetworkSelectionStatus object elements.
    859          */
    860         public static final String XML_TAG_SELECTION_STATUS = "SelectionStatus";
    861         public static final String XML_TAG_DISABLE_REASON = "DisableReason";
    862         public static final String XML_TAG_CONNECT_CHOICE = "ConnectChoice";
    863         public static final String XML_TAG_CONNECT_CHOICE_TIMESTAMP = "ConnectChoiceTimeStamp";
    864         public static final String XML_TAG_HAS_EVER_CONNECTED = "HasEverConnected";
    865 
    866         /**
    867          * Write the NetworkSelectionStatus data elements from the provided status to the XML
    868          * stream.
    869          *
    870          * @param out             XmlSerializer instance pointing to the XML stream.
    871          * @param selectionStatus NetworkSelectionStatus object to be serialized.
    872          */
    873         public static void writeToXml(XmlSerializer out, NetworkSelectionStatus selectionStatus)
    874                 throws XmlPullParserException, IOException {
    875             XmlUtil.writeNextValue(
    876                     out, XML_TAG_SELECTION_STATUS, selectionStatus.getNetworkStatusString());
    877             XmlUtil.writeNextValue(
    878                     out, XML_TAG_DISABLE_REASON, selectionStatus.getNetworkDisableReasonString());
    879             XmlUtil.writeNextValue(out, XML_TAG_CONNECT_CHOICE, selectionStatus.getConnectChoice());
    880             XmlUtil.writeNextValue(
    881                     out, XML_TAG_CONNECT_CHOICE_TIMESTAMP,
    882                     selectionStatus.getConnectChoiceTimestamp());
    883             XmlUtil.writeNextValue(
    884                     out, XML_TAG_HAS_EVER_CONNECTED, selectionStatus.getHasEverConnected());
    885         }
    886 
    887         /**
    888          * Parses the NetworkSelectionStatus data elements from the provided XML stream to a
    889          * NetworkSelectionStatus object.
    890          *
    891          * @param in            XmlPullParser instance pointing to the XML stream.
    892          * @param outerTagDepth depth of the outer tag in the XML document.
    893          * @return NetworkSelectionStatus object if parsing is successful, null otherwise.
    894          */
    895         public static NetworkSelectionStatus parseFromXml(XmlPullParser in, int outerTagDepth)
    896                 throws XmlPullParserException, IOException {
    897             NetworkSelectionStatus selectionStatus = new NetworkSelectionStatus();
    898             String statusString = "";
    899             String disableReasonString = "";
    900 
    901             // Loop through and parse out all the elements from the stream within this section.
    902             while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
    903                 String[] valueName = new String[1];
    904                 Object value = XmlUtil.readCurrentValue(in, valueName);
    905                 if (valueName[0] == null) {
    906                     throw new XmlPullParserException("Missing value name");
    907                 }
    908                 switch (valueName[0]) {
    909                     case XML_TAG_SELECTION_STATUS:
    910                         statusString = (String) value;
    911                         break;
    912                     case XML_TAG_DISABLE_REASON:
    913                         disableReasonString = (String) value;
    914                         break;
    915                     case XML_TAG_CONNECT_CHOICE:
    916                         selectionStatus.setConnectChoice((String) value);
    917                         break;
    918                     case XML_TAG_CONNECT_CHOICE_TIMESTAMP:
    919                         selectionStatus.setConnectChoiceTimestamp((long) value);
    920                         break;
    921                     case XML_TAG_HAS_EVER_CONNECTED:
    922                         selectionStatus.setHasEverConnected((boolean) value);
    923                         break;
    924                     default:
    925                         throw new XmlPullParserException(
    926                                 "Unknown value name found: " + valueName[0]);
    927                 }
    928             }
    929             // Now figure out the network selection status codes from |selectionStatusString| &
    930             // |disableReasonString|.
    931             int status =
    932                     Arrays.asList(NetworkSelectionStatus.QUALITY_NETWORK_SELECTION_STATUS)
    933                             .indexOf(statusString);
    934             int disableReason =
    935                     Arrays.asList(NetworkSelectionStatus.QUALITY_NETWORK_SELECTION_DISABLE_REASON)
    936                             .indexOf(disableReasonString);
    937 
    938             // If either of the above codes are invalid or if the network was temporarily disabled
    939             // (blacklisted), restore the status as enabled. We don't want to persist blacklists
    940             // across reboots.
    941             if (status == -1 || disableReason == -1 ||
    942                     status == NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED) {
    943                 status = NetworkSelectionStatus.NETWORK_SELECTION_ENABLED;
    944                 disableReason = NetworkSelectionStatus.NETWORK_SELECTION_ENABLE;
    945             }
    946             selectionStatus.setNetworkSelectionStatus(status);
    947             selectionStatus.setNetworkSelectionDisableReason(disableReason);
    948             return selectionStatus;
    949         }
    950     }
    951 
    952     /**
    953      * Utility class to serialize and deseriaize {@link WifiEnterpriseConfig} object to XML &
    954      * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module.
    955      */
    956     public static class WifiEnterpriseConfigXmlUtil {
    957 
    958         /**
    959          * List of XML tags corresponding to WifiEnterpriseConfig object elements.
    960          */
    961         public static final String XML_TAG_IDENTITY = "Identity";
    962         public static final String XML_TAG_ANON_IDENTITY = "AnonIdentity";
    963         public static final String XML_TAG_PASSWORD = "Password";
    964         public static final String XML_TAG_CLIENT_CERT = "ClientCert";
    965         public static final String XML_TAG_CA_CERT = "CaCert";
    966         public static final String XML_TAG_SUBJECT_MATCH = "SubjectMatch";
    967         public static final String XML_TAG_ENGINE = "Engine";
    968         public static final String XML_TAG_ENGINE_ID = "EngineId";
    969         public static final String XML_TAG_PRIVATE_KEY_ID = "PrivateKeyId";
    970         public static final String XML_TAG_ALT_SUBJECT_MATCH = "AltSubjectMatch";
    971         public static final String XML_TAG_DOM_SUFFIX_MATCH = "DomSuffixMatch";
    972         public static final String XML_TAG_CA_PATH = "CaPath";
    973         public static final String XML_TAG_EAP_METHOD = "EapMethod";
    974         public static final String XML_TAG_PHASE2_METHOD = "Phase2Method";
    975         public static final String XML_TAG_PLMN = "PLMN";
    976         public static final String XML_TAG_REALM = "Realm";
    977 
    978         /**
    979          * Write the WifiEnterpriseConfig data elements from the provided config to the XML
    980          * stream.
    981          *
    982          * @param out              XmlSerializer instance pointing to the XML stream.
    983          * @param enterpriseConfig WifiEnterpriseConfig object to be serialized.
    984          */
    985         public static void writeToXml(XmlSerializer out, WifiEnterpriseConfig enterpriseConfig)
    986                 throws XmlPullParserException, IOException {
    987             XmlUtil.writeNextValue(out, XML_TAG_IDENTITY,
    988                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.IDENTITY_KEY));
    989             XmlUtil.writeNextValue(out, XML_TAG_ANON_IDENTITY,
    990                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY));
    991             XmlUtil.writeNextValue(out, XML_TAG_PASSWORD,
    992                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY));
    993             XmlUtil.writeNextValue(out, XML_TAG_CLIENT_CERT,
    994                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY));
    995             XmlUtil.writeNextValue(out, XML_TAG_CA_CERT,
    996                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY));
    997             XmlUtil.writeNextValue(out, XML_TAG_SUBJECT_MATCH,
    998                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY));
    999             XmlUtil.writeNextValue(out, XML_TAG_ENGINE,
   1000                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_KEY));
   1001             XmlUtil.writeNextValue(out, XML_TAG_ENGINE_ID,
   1002                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY));
   1003             XmlUtil.writeNextValue(out, XML_TAG_PRIVATE_KEY_ID,
   1004                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY));
   1005             XmlUtil.writeNextValue(out, XML_TAG_ALT_SUBJECT_MATCH,
   1006                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY));
   1007             XmlUtil.writeNextValue(out, XML_TAG_DOM_SUFFIX_MATCH,
   1008                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY));
   1009             XmlUtil.writeNextValue(out, XML_TAG_CA_PATH,
   1010                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_PATH_KEY));
   1011             XmlUtil.writeNextValue(out, XML_TAG_EAP_METHOD, enterpriseConfig.getEapMethod());
   1012             XmlUtil.writeNextValue(out, XML_TAG_PHASE2_METHOD, enterpriseConfig.getPhase2Method());
   1013             XmlUtil.writeNextValue(out, XML_TAG_PLMN, enterpriseConfig.getPlmn());
   1014             XmlUtil.writeNextValue(out, XML_TAG_REALM, enterpriseConfig.getRealm());
   1015         }
   1016 
   1017         /**
   1018          * Parses the data elements from the provided XML stream to a WifiEnterpriseConfig object.
   1019          *
   1020          * @param in            XmlPullParser instance pointing to the XML stream.
   1021          * @param outerTagDepth depth of the outer tag in the XML document.
   1022          * @return WifiEnterpriseConfig object if parsing is successful, null otherwise.
   1023          */
   1024         public static WifiEnterpriseConfig parseFromXml(XmlPullParser in, int outerTagDepth)
   1025                 throws XmlPullParserException, IOException {
   1026             WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
   1027 
   1028             // Loop through and parse out all the elements from the stream within this section.
   1029             while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
   1030                 String[] valueName = new String[1];
   1031                 Object value = XmlUtil.readCurrentValue(in, valueName);
   1032                 if (valueName[0] == null) {
   1033                     throw new XmlPullParserException("Missing value name");
   1034                 }
   1035                 switch (valueName[0]) {
   1036                     case XML_TAG_IDENTITY:
   1037                         enterpriseConfig.setFieldValue(
   1038                                 WifiEnterpriseConfig.IDENTITY_KEY, (String) value);
   1039                         break;
   1040                     case XML_TAG_ANON_IDENTITY:
   1041                         enterpriseConfig.setFieldValue(
   1042                                 WifiEnterpriseConfig.ANON_IDENTITY_KEY, (String) value);
   1043                         break;
   1044                     case XML_TAG_PASSWORD:
   1045                         enterpriseConfig.setFieldValue(
   1046                                 WifiEnterpriseConfig.PASSWORD_KEY, (String) value);
   1047                         break;
   1048                     case XML_TAG_CLIENT_CERT:
   1049                         enterpriseConfig.setFieldValue(
   1050                                 WifiEnterpriseConfig.CLIENT_CERT_KEY, (String) value);
   1051                         break;
   1052                     case XML_TAG_CA_CERT:
   1053                         enterpriseConfig.setFieldValue(
   1054                                 WifiEnterpriseConfig.CA_CERT_KEY, (String) value);
   1055                         break;
   1056                     case XML_TAG_SUBJECT_MATCH:
   1057                         enterpriseConfig.setFieldValue(
   1058                                 WifiEnterpriseConfig.SUBJECT_MATCH_KEY, (String) value);
   1059                         break;
   1060                     case XML_TAG_ENGINE:
   1061                         enterpriseConfig.setFieldValue(
   1062                                 WifiEnterpriseConfig.ENGINE_KEY, (String) value);
   1063                         break;
   1064                     case XML_TAG_ENGINE_ID:
   1065                         enterpriseConfig.setFieldValue(
   1066                                 WifiEnterpriseConfig.ENGINE_ID_KEY, (String) value);
   1067                         break;
   1068                     case XML_TAG_PRIVATE_KEY_ID:
   1069                         enterpriseConfig.setFieldValue(
   1070                                 WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, (String) value);
   1071                         break;
   1072                     case XML_TAG_ALT_SUBJECT_MATCH:
   1073                         enterpriseConfig.setFieldValue(
   1074                                 WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, (String) value);
   1075                         break;
   1076                     case XML_TAG_DOM_SUFFIX_MATCH:
   1077                         enterpriseConfig.setFieldValue(
   1078                                 WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, (String) value);
   1079                         break;
   1080                     case XML_TAG_CA_PATH:
   1081                         enterpriseConfig.setFieldValue(
   1082                                 WifiEnterpriseConfig.CA_PATH_KEY, (String) value);
   1083                         break;
   1084                     case XML_TAG_EAP_METHOD:
   1085                         enterpriseConfig.setEapMethod((int) value);
   1086                         break;
   1087                     case XML_TAG_PHASE2_METHOD:
   1088                         enterpriseConfig.setPhase2Method((int) value);
   1089                         break;
   1090                     case XML_TAG_PLMN:
   1091                         enterpriseConfig.setPlmn((String) value);
   1092                         break;
   1093                     case XML_TAG_REALM:
   1094                         enterpriseConfig.setRealm((String) value);
   1095                         break;
   1096                     default:
   1097                         throw new XmlPullParserException(
   1098                                 "Unknown value name found: " + valueName[0]);
   1099                 }
   1100             }
   1101             return enterpriseConfig;
   1102         }
   1103     }
   1104 }
   1105 
   1106