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