• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
gotoStartTag(XmlPullParser in)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      */
gotoEndTag(XmlPullParser in)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      */
gotoDocumentStart(XmlPullParser in, String headerName)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      */
gotoNextSectionOrEnd( XmlPullParser in, String[] headerName, int outerDepth)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      */
gotoNextSectionWithNameOrEnd( XmlPullParser in, String expectedName, int outerDepth)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      */
gotoNextSectionWithName( XmlPullParser in, String expectedName, int outerDepth)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      */
isNextSectionEnd(XmlPullParser in, int sectionDepth)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      */
readCurrentValue(XmlPullParser in, String[] valueName)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      */
readNextValueWithName(XmlPullParser in, String expectedName)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      */
writeDocumentStart(XmlSerializer out, String headerName)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      */
writeDocumentEnd(XmlSerializer out, String headerName)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      */
writeNextSectionStart(XmlSerializer out, String headerName)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      */
writeNextSectionEnd(XmlSerializer out, String headerName)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      */
writeNextValue(XmlSerializer out, String name, Object value)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_METERED_OVERRIDE = "MeteredOverride";
336         public static final String XML_TAG_USE_EXTERNAL_SCORES = "UseExternalScores";
337         public static final String XML_TAG_NUM_ASSOCIATION = "NumAssociation";
338         public static final String XML_TAG_CREATOR_UID = "CreatorUid";
339         public static final String XML_TAG_CREATOR_NAME = "CreatorName";
340         public static final String XML_TAG_CREATION_TIME = "CreationTime";
341         public static final String XML_TAG_LAST_UPDATE_UID = "LastUpdateUid";
342         public static final String XML_TAG_LAST_UPDATE_NAME = "LastUpdateName";
343         public static final String XML_TAG_LAST_CONNECT_UID = "LastConnectUid";
344         public static final String XML_TAG_IS_LEGACY_PASSPOINT_CONFIG = "IsLegacyPasspointConfig";
345         public static final String XML_TAG_ROAMING_CONSORTIUM_OIS = "RoamingConsortiumOIs";
346 
347         /**
348          * Write WepKeys to the XML stream.
349          * WepKeys array is intialized in WifiConfiguration constructor, but all of the elements
350          * are set to null. User may chose to set any one of the key elements in WifiConfiguration.
351          * XmlUtils serialization doesn't handle this array of nulls well .
352          * So, write empty strings if some of the keys are not initialized and null if all of
353          * the elements are empty.
354          */
writeWepKeysToXml(XmlSerializer out, String[] wepKeys)355         private static void writeWepKeysToXml(XmlSerializer out, String[] wepKeys)
356                 throws XmlPullParserException, IOException {
357             String[] wepKeysToWrite = new String[wepKeys.length];
358             boolean hasWepKey = false;
359             for (int i = 0; i < wepKeys.length; i++) {
360                 if (wepKeys[i] == null) {
361                     wepKeysToWrite[i] = new String();
362                 } else {
363                     wepKeysToWrite[i] = wepKeys[i];
364                     hasWepKey = true;
365                 }
366             }
367             if (hasWepKey) {
368                 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, wepKeysToWrite);
369             } else {
370                 XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, null);
371             }
372         }
373 
374         /**
375          * Write the Configuration data elements that are common for backup & config store to the
376          * XML stream.
377          *
378          * @param out           XmlSerializer instance pointing to the XML stream.
379          * @param configuration WifiConfiguration object to be serialized.
380          */
writeCommonElementsToXml( XmlSerializer out, WifiConfiguration configuration)381         public static void writeCommonElementsToXml(
382                 XmlSerializer out, WifiConfiguration configuration)
383                 throws XmlPullParserException, IOException {
384             XmlUtil.writeNextValue(out, XML_TAG_CONFIG_KEY, configuration.configKey());
385             XmlUtil.writeNextValue(out, XML_TAG_SSID, configuration.SSID);
386             XmlUtil.writeNextValue(out, XML_TAG_BSSID, configuration.BSSID);
387             XmlUtil.writeNextValue(out, XML_TAG_PRE_SHARED_KEY, configuration.preSharedKey);
388             writeWepKeysToXml(out, configuration.wepKeys);
389             XmlUtil.writeNextValue(out, XML_TAG_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex);
390             XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, configuration.hiddenSSID);
391             XmlUtil.writeNextValue(out, XML_TAG_REQUIRE_PMF, configuration.requirePMF);
392             XmlUtil.writeNextValue(
393                     out, XML_TAG_ALLOWED_KEY_MGMT,
394                     configuration.allowedKeyManagement.toByteArray());
395             XmlUtil.writeNextValue(
396                     out, XML_TAG_ALLOWED_PROTOCOLS,
397                     configuration.allowedProtocols.toByteArray());
398             XmlUtil.writeNextValue(
399                     out, XML_TAG_ALLOWED_AUTH_ALGOS,
400                     configuration.allowedAuthAlgorithms.toByteArray());
401             XmlUtil.writeNextValue(
402                     out, XML_TAG_ALLOWED_GROUP_CIPHERS,
403                     configuration.allowedGroupCiphers.toByteArray());
404             XmlUtil.writeNextValue(
405                     out, XML_TAG_ALLOWED_PAIRWISE_CIPHERS,
406                     configuration.allowedPairwiseCiphers.toByteArray());
407             XmlUtil.writeNextValue(out, XML_TAG_SHARED, configuration.shared);
408         }
409 
410         /**
411          * Write the Configuration data elements for backup from the provided Configuration to the
412          * XML stream.
413          * Note: This is a subset of the elements serialized for config store.
414          *
415          * @param out           XmlSerializer instance pointing to the XML stream.
416          * @param configuration WifiConfiguration object to be serialized.
417          */
writeToXmlForBackup(XmlSerializer out, WifiConfiguration configuration)418         public static void writeToXmlForBackup(XmlSerializer out, WifiConfiguration configuration)
419                 throws XmlPullParserException, IOException {
420             writeCommonElementsToXml(out, configuration);
421         }
422 
423         /**
424          * Write the Configuration data elements for config store from the provided Configuration
425          * to the XML stream.
426          *
427          * @param out           XmlSerializer instance pointing to the XML stream.
428          * @param configuration WifiConfiguration object to be serialized.
429          */
writeToXmlForConfigStore( XmlSerializer out, WifiConfiguration configuration)430         public static void writeToXmlForConfigStore(
431                 XmlSerializer out, WifiConfiguration configuration)
432                 throws XmlPullParserException, IOException {
433             writeCommonElementsToXml(out, configuration);
434             XmlUtil.writeNextValue(out, XML_TAG_STATUS, configuration.status);
435             XmlUtil.writeNextValue(out, XML_TAG_FQDN, configuration.FQDN);
436             XmlUtil.writeNextValue(
437                     out, XML_TAG_PROVIDER_FRIENDLY_NAME, configuration.providerFriendlyName);
438             XmlUtil.writeNextValue(
439                     out, XML_TAG_LINKED_NETWORKS_LIST, configuration.linkedConfigurations);
440             XmlUtil.writeNextValue(
441                     out, XML_TAG_DEFAULT_GW_MAC_ADDRESS, configuration.defaultGwMacAddress);
442             XmlUtil.writeNextValue(
443                     out, XML_TAG_VALIDATED_INTERNET_ACCESS, configuration.validatedInternetAccess);
444             XmlUtil.writeNextValue(
445                     out, XML_TAG_NO_INTERNET_ACCESS_EXPECTED,
446                     configuration.noInternetAccessExpected);
447             XmlUtil.writeNextValue(out, XML_TAG_USER_APPROVED, configuration.userApproved);
448             XmlUtil.writeNextValue(out, XML_TAG_METERED_HINT, configuration.meteredHint);
449             XmlUtil.writeNextValue(out, XML_TAG_METERED_OVERRIDE, configuration.meteredOverride);
450             XmlUtil.writeNextValue(
451                     out, XML_TAG_USE_EXTERNAL_SCORES, configuration.useExternalScores);
452             XmlUtil.writeNextValue(out, XML_TAG_NUM_ASSOCIATION, configuration.numAssociation);
453             XmlUtil.writeNextValue(out, XML_TAG_CREATOR_UID, configuration.creatorUid);
454             XmlUtil.writeNextValue(out, XML_TAG_CREATOR_NAME, configuration.creatorName);
455             XmlUtil.writeNextValue(out, XML_TAG_CREATION_TIME, configuration.creationTime);
456             XmlUtil.writeNextValue(out, XML_TAG_LAST_UPDATE_UID, configuration.lastUpdateUid);
457             XmlUtil.writeNextValue(out, XML_TAG_LAST_UPDATE_NAME, configuration.lastUpdateName);
458             XmlUtil.writeNextValue(out, XML_TAG_LAST_CONNECT_UID, configuration.lastConnectUid);
459             XmlUtil.writeNextValue(
460                     out, XML_TAG_IS_LEGACY_PASSPOINT_CONFIG,
461                     configuration.isLegacyPasspointConfig);
462             XmlUtil.writeNextValue(
463                     out, XML_TAG_ROAMING_CONSORTIUM_OIS, configuration.roamingConsortiumIds);
464         }
465 
466         /**
467          * Populate wepKeys array elements only if they were non-empty in the backup data.
468          *
469          * @throws XmlPullParserException if parsing errors occur.
470          */
populateWepKeysFromXmlValue(Object value, String[] wepKeys)471         private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys)
472                 throws XmlPullParserException, IOException {
473             String[] wepKeysInData = (String[]) value;
474             if (wepKeysInData == null) {
475                 return;
476             }
477             if (wepKeysInData.length != wepKeys.length) {
478                 throw new XmlPullParserException(
479                         "Invalid Wep Keys length: " + wepKeysInData.length);
480             }
481             for (int i = 0; i < wepKeys.length; i++) {
482                 if (wepKeysInData[i].isEmpty()) {
483                     wepKeys[i] = null;
484                 } else {
485                     wepKeys[i] = wepKeysInData[i];
486                 }
487             }
488         }
489 
490         /**
491          * Parses the configuration data elements from the provided XML stream to a
492          * WifiConfiguration object.
493          * Note: This is used for parsing both backup data and config store data. Looping through
494          * the tags make it easy to add or remove elements in the future versions if needed.
495          *
496          * @param in            XmlPullParser instance pointing to the XML stream.
497          * @param outerTagDepth depth of the outer tag in the XML document.
498          * @return Pair<Config key, WifiConfiguration object> if parsing is successful,
499          * null otherwise.
500          */
parseFromXml( XmlPullParser in, int outerTagDepth)501         public static Pair<String, WifiConfiguration> parseFromXml(
502                 XmlPullParser in, int outerTagDepth)
503                 throws XmlPullParserException, IOException {
504             WifiConfiguration configuration = new WifiConfiguration();
505             String configKeyInData = null;
506 
507             // Loop through and parse out all the elements from the stream within this section.
508             while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
509                 String[] valueName = new String[1];
510                 Object value = XmlUtil.readCurrentValue(in, valueName);
511                 if (valueName[0] == null) {
512                     throw new XmlPullParserException("Missing value name");
513                 }
514                 switch (valueName[0]) {
515                     case XML_TAG_CONFIG_KEY:
516                         configKeyInData = (String) value;
517                         break;
518                     case XML_TAG_SSID:
519                         configuration.SSID = (String) value;
520                         break;
521                     case XML_TAG_BSSID:
522                         configuration.BSSID = (String) value;
523                         break;
524                     case XML_TAG_PRE_SHARED_KEY:
525                         configuration.preSharedKey = (String) value;
526                         break;
527                     case XML_TAG_WEP_KEYS:
528                         populateWepKeysFromXmlValue(value, configuration.wepKeys);
529                         break;
530                     case XML_TAG_WEP_TX_KEY_INDEX:
531                         configuration.wepTxKeyIndex = (int) value;
532                         break;
533                     case XML_TAG_HIDDEN_SSID:
534                         configuration.hiddenSSID = (boolean) value;
535                         break;
536                     case XML_TAG_REQUIRE_PMF:
537                         configuration.requirePMF = (boolean) value;
538                         break;
539                     case XML_TAG_ALLOWED_KEY_MGMT:
540                         byte[] allowedKeyMgmt = (byte[]) value;
541                         configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt);
542                         break;
543                     case XML_TAG_ALLOWED_PROTOCOLS:
544                         byte[] allowedProtocols = (byte[]) value;
545                         configuration.allowedProtocols = BitSet.valueOf(allowedProtocols);
546                         break;
547                     case XML_TAG_ALLOWED_AUTH_ALGOS:
548                         byte[] allowedAuthAlgorithms = (byte[]) value;
549                         configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms);
550                         break;
551                     case XML_TAG_ALLOWED_GROUP_CIPHERS:
552                         byte[] allowedGroupCiphers = (byte[]) value;
553                         configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers);
554                         break;
555                     case XML_TAG_ALLOWED_PAIRWISE_CIPHERS:
556                         byte[] allowedPairwiseCiphers = (byte[]) value;
557                         configuration.allowedPairwiseCiphers =
558                                 BitSet.valueOf(allowedPairwiseCiphers);
559                         break;
560                     case XML_TAG_SHARED:
561                         configuration.shared = (boolean) value;
562                         break;
563                     case XML_TAG_STATUS:
564                         int status = (int) value;
565                         // Any network which was CURRENT before reboot needs
566                         // to be restored to ENABLED.
567                         if (status == WifiConfiguration.Status.CURRENT) {
568                             status = WifiConfiguration.Status.ENABLED;
569                         }
570                         configuration.status = status;
571                         break;
572                     case XML_TAG_FQDN:
573                         configuration.FQDN = (String) value;
574                         break;
575                     case XML_TAG_PROVIDER_FRIENDLY_NAME:
576                         configuration.providerFriendlyName = (String) value;
577                         break;
578                     case XML_TAG_LINKED_NETWORKS_LIST:
579                         configuration.linkedConfigurations = (HashMap<String, Integer>) value;
580                         break;
581                     case XML_TAG_DEFAULT_GW_MAC_ADDRESS:
582                         configuration.defaultGwMacAddress = (String) value;
583                         break;
584                     case XML_TAG_VALIDATED_INTERNET_ACCESS:
585                         configuration.validatedInternetAccess = (boolean) value;
586                         break;
587                     case XML_TAG_NO_INTERNET_ACCESS_EXPECTED:
588                         configuration.noInternetAccessExpected = (boolean) value;
589                         break;
590                     case XML_TAG_USER_APPROVED:
591                         configuration.userApproved = (int) value;
592                         break;
593                     case XML_TAG_METERED_HINT:
594                         configuration.meteredHint = (boolean) value;
595                         break;
596                     case XML_TAG_METERED_OVERRIDE:
597                         configuration.meteredOverride = (int) value;
598                         break;
599                     case XML_TAG_USE_EXTERNAL_SCORES:
600                         configuration.useExternalScores = (boolean) value;
601                         break;
602                     case XML_TAG_NUM_ASSOCIATION:
603                         configuration.numAssociation = (int) value;
604                         break;
605                     case XML_TAG_CREATOR_UID:
606                         configuration.creatorUid = (int) value;
607                         break;
608                     case XML_TAG_CREATOR_NAME:
609                         configuration.creatorName = (String) value;
610                         break;
611                     case XML_TAG_CREATION_TIME:
612                         configuration.creationTime = (String) value;
613                         break;
614                     case XML_TAG_LAST_UPDATE_UID:
615                         configuration.lastUpdateUid = (int) value;
616                         break;
617                     case XML_TAG_LAST_UPDATE_NAME:
618                         configuration.lastUpdateName = (String) value;
619                         break;
620                     case XML_TAG_LAST_CONNECT_UID:
621                         configuration.lastConnectUid = (int) value;
622                         break;
623                     case XML_TAG_IS_LEGACY_PASSPOINT_CONFIG:
624                         configuration.isLegacyPasspointConfig = (boolean) value;
625                         break;
626                     case XML_TAG_ROAMING_CONSORTIUM_OIS:
627                         configuration.roamingConsortiumIds = (long[]) value;
628                         break;
629                     default:
630                         throw new XmlPullParserException(
631                                 "Unknown value name found: " + valueName[0]);
632                 }
633             }
634             return Pair.create(configKeyInData, configuration);
635         }
636     }
637 
638     /**
639      * Utility class to serialize and deseriaize {@link IpConfiguration} object to XML & vice versa.
640      * This is used by both {@link com.android.server.wifi.WifiConfigStore} &
641      * {@link com.android.server.wifi.WifiBackupRestore} modules.
642      */
643     public static class IpConfigurationXmlUtil {
644 
645         /**
646          * List of XML tags corresponding to IpConfiguration object elements.
647          */
648         public static final String XML_TAG_IP_ASSIGNMENT = "IpAssignment";
649         public static final String XML_TAG_LINK_ADDRESS = "LinkAddress";
650         public static final String XML_TAG_LINK_PREFIX_LENGTH = "LinkPrefixLength";
651         public static final String XML_TAG_GATEWAY_ADDRESS = "GatewayAddress";
652         public static final String XML_TAG_DNS_SERVER_ADDRESSES = "DNSServers";
653         public static final String XML_TAG_PROXY_SETTINGS = "ProxySettings";
654         public static final String XML_TAG_PROXY_HOST = "ProxyHost";
655         public static final String XML_TAG_PROXY_PORT = "ProxyPort";
656         public static final String XML_TAG_PROXY_PAC_FILE = "ProxyPac";
657         public static final String XML_TAG_PROXY_EXCLUSION_LIST = "ProxyExclusionList";
658 
659         /**
660          * Write the static IP configuration data elements to XML stream.
661          */
writeStaticIpConfigurationToXml( XmlSerializer out, StaticIpConfiguration staticIpConfiguration)662         private static void writeStaticIpConfigurationToXml(
663                 XmlSerializer out, StaticIpConfiguration staticIpConfiguration)
664                 throws XmlPullParserException, IOException {
665             if (staticIpConfiguration.ipAddress != null) {
666                 XmlUtil.writeNextValue(
667                         out, XML_TAG_LINK_ADDRESS,
668                         staticIpConfiguration.ipAddress.getAddress().getHostAddress());
669                 XmlUtil.writeNextValue(
670                         out, XML_TAG_LINK_PREFIX_LENGTH,
671                         staticIpConfiguration.ipAddress.getPrefixLength());
672             } else {
673                 XmlUtil.writeNextValue(
674                         out, XML_TAG_LINK_ADDRESS, null);
675                 XmlUtil.writeNextValue(
676                         out, XML_TAG_LINK_PREFIX_LENGTH, null);
677             }
678             if (staticIpConfiguration.gateway != null) {
679                 XmlUtil.writeNextValue(
680                         out, XML_TAG_GATEWAY_ADDRESS,
681                         staticIpConfiguration.gateway.getHostAddress());
682             } else {
683                 XmlUtil.writeNextValue(
684                         out, XML_TAG_GATEWAY_ADDRESS, null);
685 
686             }
687             if (staticIpConfiguration.dnsServers != null) {
688                 // Create a string array of DNS server addresses
689                 String[] dnsServers = new String[staticIpConfiguration.dnsServers.size()];
690                 int dnsServerIdx = 0;
691                 for (InetAddress inetAddr : staticIpConfiguration.dnsServers) {
692                     dnsServers[dnsServerIdx++] = inetAddr.getHostAddress();
693                 }
694                 XmlUtil.writeNextValue(
695                         out, XML_TAG_DNS_SERVER_ADDRESSES, dnsServers);
696             } else {
697                 XmlUtil.writeNextValue(
698                         out, XML_TAG_DNS_SERVER_ADDRESSES, null);
699             }
700         }
701 
702         /**
703          * Write the IP configuration data elements from the provided Configuration to the XML
704          * stream.
705          *
706          * @param out             XmlSerializer instance pointing to the XML stream.
707          * @param ipConfiguration IpConfiguration object to be serialized.
708          */
writeToXml(XmlSerializer out, IpConfiguration ipConfiguration)709         public static void writeToXml(XmlSerializer out, IpConfiguration ipConfiguration)
710                 throws XmlPullParserException, IOException {
711             // Write IP assignment settings
712             XmlUtil.writeNextValue(out, XML_TAG_IP_ASSIGNMENT,
713                     ipConfiguration.ipAssignment.toString());
714             switch (ipConfiguration.ipAssignment) {
715                 case STATIC:
716                     writeStaticIpConfigurationToXml(
717                             out, ipConfiguration.getStaticIpConfiguration());
718                     break;
719                 default:
720                     break;
721             }
722 
723             // Write proxy settings
724             XmlUtil.writeNextValue(
725                     out, XML_TAG_PROXY_SETTINGS,
726                     ipConfiguration.proxySettings.toString());
727             switch (ipConfiguration.proxySettings) {
728                 case STATIC:
729                     XmlUtil.writeNextValue(
730                             out, XML_TAG_PROXY_HOST,
731                             ipConfiguration.httpProxy.getHost());
732                     XmlUtil.writeNextValue(
733                             out, XML_TAG_PROXY_PORT,
734                             ipConfiguration.httpProxy.getPort());
735                     XmlUtil.writeNextValue(
736                             out, XML_TAG_PROXY_EXCLUSION_LIST,
737                             ipConfiguration.httpProxy.getExclusionListAsString());
738                     break;
739                 case PAC:
740                     XmlUtil.writeNextValue(
741                             out, XML_TAG_PROXY_PAC_FILE,
742                             ipConfiguration.httpProxy.getPacFileUrl().toString());
743                     break;
744                 default:
745                     break;
746             }
747         }
748 
749         /**
750          * Parse out the static IP configuration from the XML stream.
751          */
parseStaticIpConfigurationFromXml(XmlPullParser in)752         private static StaticIpConfiguration parseStaticIpConfigurationFromXml(XmlPullParser in)
753                 throws XmlPullParserException, IOException {
754             StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
755 
756             String linkAddressString =
757                     (String) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_ADDRESS);
758             Integer linkPrefixLength =
759                     (Integer) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_PREFIX_LENGTH);
760             if (linkAddressString != null && linkPrefixLength != null) {
761                 LinkAddress linkAddress = new LinkAddress(
762                         NetworkUtils.numericToInetAddress(linkAddressString),
763                         linkPrefixLength);
764                 if (linkAddress.getAddress() instanceof Inet4Address) {
765                     staticIpConfiguration.ipAddress = linkAddress;
766                 } else {
767                     Log.w(TAG, "Non-IPv4 address: " + linkAddress);
768                 }
769             }
770             String gatewayAddressString =
771                     (String) XmlUtil.readNextValueWithName(in, XML_TAG_GATEWAY_ADDRESS);
772             if (gatewayAddressString != null) {
773                 LinkAddress dest = null;
774                 InetAddress gateway =
775                         NetworkUtils.numericToInetAddress(gatewayAddressString);
776                 RouteInfo route = new RouteInfo(dest, gateway);
777                 if (route.isIPv4Default()) {
778                     staticIpConfiguration.gateway = gateway;
779                 } else {
780                     Log.w(TAG, "Non-IPv4 default route: " + route);
781                 }
782             }
783             String[] dnsServerAddressesString =
784                     (String[]) XmlUtil.readNextValueWithName(in, XML_TAG_DNS_SERVER_ADDRESSES);
785             if (dnsServerAddressesString != null) {
786                 for (String dnsServerAddressString : dnsServerAddressesString) {
787                     InetAddress dnsServerAddress =
788                             NetworkUtils.numericToInetAddress(dnsServerAddressString);
789                     staticIpConfiguration.dnsServers.add(dnsServerAddress);
790                 }
791             }
792             return staticIpConfiguration;
793         }
794 
795         /**
796          * Parses the IP configuration data elements from the provided XML stream to an
797          * IpConfiguration object.
798          *
799          * @param in            XmlPullParser instance pointing to the XML stream.
800          * @param outerTagDepth depth of the outer tag in the XML document.
801          * @return IpConfiguration object if parsing is successful, null otherwise.
802          */
parseFromXml(XmlPullParser in, int outerTagDepth)803         public static IpConfiguration parseFromXml(XmlPullParser in, int outerTagDepth)
804                 throws XmlPullParserException, IOException {
805             IpConfiguration ipConfiguration = new IpConfiguration();
806 
807             // Parse out the IP assignment info first.
808             String ipAssignmentString =
809                     (String) XmlUtil.readNextValueWithName(in, XML_TAG_IP_ASSIGNMENT);
810             IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString);
811             ipConfiguration.setIpAssignment(ipAssignment);
812             switch (ipAssignment) {
813                 case STATIC:
814                     ipConfiguration.setStaticIpConfiguration(parseStaticIpConfigurationFromXml(in));
815                     break;
816                 case DHCP:
817                 case UNASSIGNED:
818                     break;
819                 default:
820                     throw new XmlPullParserException("Unknown ip assignment type: " + ipAssignment);
821             }
822 
823             // Parse out the proxy settings next.
824             String proxySettingsString =
825                     (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_SETTINGS);
826             ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString);
827             ipConfiguration.setProxySettings(proxySettings);
828             switch (proxySettings) {
829                 case STATIC:
830                     String proxyHost =
831                             (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_HOST);
832                     int proxyPort =
833                             (int) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PORT);
834                     String proxyExclusionList =
835                             (String) XmlUtil.readNextValueWithName(
836                                     in, XML_TAG_PROXY_EXCLUSION_LIST);
837                     ipConfiguration.setHttpProxy(
838                             new ProxyInfo(proxyHost, proxyPort, proxyExclusionList));
839                     break;
840                 case PAC:
841                     String proxyPacFile =
842                             (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PAC_FILE);
843                     ipConfiguration.setHttpProxy(new ProxyInfo(proxyPacFile));
844                     break;
845                 case NONE:
846                 case UNASSIGNED:
847                     break;
848                 default:
849                     throw new XmlPullParserException(
850                             "Unknown proxy settings type: " + proxySettings);
851             }
852             return ipConfiguration;
853         }
854     }
855 
856     /**
857      * Utility class to serialize and deseriaize {@link NetworkSelectionStatus} object to XML &
858      * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module.
859      */
860     public static class NetworkSelectionStatusXmlUtil {
861 
862         /**
863          * List of XML tags corresponding to NetworkSelectionStatus object elements.
864          */
865         public static final String XML_TAG_SELECTION_STATUS = "SelectionStatus";
866         public static final String XML_TAG_DISABLE_REASON = "DisableReason";
867         public static final String XML_TAG_CONNECT_CHOICE = "ConnectChoice";
868         public static final String XML_TAG_CONNECT_CHOICE_TIMESTAMP = "ConnectChoiceTimeStamp";
869         public static final String XML_TAG_HAS_EVER_CONNECTED = "HasEverConnected";
870 
871         /**
872          * Write the NetworkSelectionStatus data elements from the provided status to the XML
873          * stream.
874          *
875          * @param out             XmlSerializer instance pointing to the XML stream.
876          * @param selectionStatus NetworkSelectionStatus object to be serialized.
877          */
writeToXml(XmlSerializer out, NetworkSelectionStatus selectionStatus)878         public static void writeToXml(XmlSerializer out, NetworkSelectionStatus selectionStatus)
879                 throws XmlPullParserException, IOException {
880             XmlUtil.writeNextValue(
881                     out, XML_TAG_SELECTION_STATUS, selectionStatus.getNetworkStatusString());
882             XmlUtil.writeNextValue(
883                     out, XML_TAG_DISABLE_REASON, selectionStatus.getNetworkDisableReasonString());
884             XmlUtil.writeNextValue(out, XML_TAG_CONNECT_CHOICE, selectionStatus.getConnectChoice());
885             XmlUtil.writeNextValue(
886                     out, XML_TAG_CONNECT_CHOICE_TIMESTAMP,
887                     selectionStatus.getConnectChoiceTimestamp());
888             XmlUtil.writeNextValue(
889                     out, XML_TAG_HAS_EVER_CONNECTED, selectionStatus.getHasEverConnected());
890         }
891 
892         /**
893          * Parses the NetworkSelectionStatus data elements from the provided XML stream to a
894          * NetworkSelectionStatus object.
895          *
896          * @param in            XmlPullParser instance pointing to the XML stream.
897          * @param outerTagDepth depth of the outer tag in the XML document.
898          * @return NetworkSelectionStatus object if parsing is successful, null otherwise.
899          */
parseFromXml(XmlPullParser in, int outerTagDepth)900         public static NetworkSelectionStatus parseFromXml(XmlPullParser in, int outerTagDepth)
901                 throws XmlPullParserException, IOException {
902             NetworkSelectionStatus selectionStatus = new NetworkSelectionStatus();
903             String statusString = "";
904             String disableReasonString = "";
905 
906             // Loop through and parse out all the elements from the stream within this section.
907             while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
908                 String[] valueName = new String[1];
909                 Object value = XmlUtil.readCurrentValue(in, valueName);
910                 if (valueName[0] == null) {
911                     throw new XmlPullParserException("Missing value name");
912                 }
913                 switch (valueName[0]) {
914                     case XML_TAG_SELECTION_STATUS:
915                         statusString = (String) value;
916                         break;
917                     case XML_TAG_DISABLE_REASON:
918                         disableReasonString = (String) value;
919                         break;
920                     case XML_TAG_CONNECT_CHOICE:
921                         selectionStatus.setConnectChoice((String) value);
922                         break;
923                     case XML_TAG_CONNECT_CHOICE_TIMESTAMP:
924                         selectionStatus.setConnectChoiceTimestamp((long) value);
925                         break;
926                     case XML_TAG_HAS_EVER_CONNECTED:
927                         selectionStatus.setHasEverConnected((boolean) value);
928                         break;
929                     default:
930                         throw new XmlPullParserException(
931                                 "Unknown value name found: " + valueName[0]);
932                 }
933             }
934             // Now figure out the network selection status codes from |selectionStatusString| &
935             // |disableReasonString|.
936             int status =
937                     Arrays.asList(NetworkSelectionStatus.QUALITY_NETWORK_SELECTION_STATUS)
938                             .indexOf(statusString);
939             int disableReason =
940                     Arrays.asList(NetworkSelectionStatus.QUALITY_NETWORK_SELECTION_DISABLE_REASON)
941                             .indexOf(disableReasonString);
942 
943             // If either of the above codes are invalid or if the network was temporarily disabled
944             // (blacklisted), restore the status as enabled. We don't want to persist blacklists
945             // across reboots.
946             if (status == -1 || disableReason == -1 ||
947                     status == NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED) {
948                 status = NetworkSelectionStatus.NETWORK_SELECTION_ENABLED;
949                 disableReason = NetworkSelectionStatus.NETWORK_SELECTION_ENABLE;
950             }
951             selectionStatus.setNetworkSelectionStatus(status);
952             selectionStatus.setNetworkSelectionDisableReason(disableReason);
953             return selectionStatus;
954         }
955     }
956 
957     /**
958      * Utility class to serialize and deseriaize {@link WifiEnterpriseConfig} object to XML &
959      * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module.
960      */
961     public static class WifiEnterpriseConfigXmlUtil {
962 
963         /**
964          * List of XML tags corresponding to WifiEnterpriseConfig object elements.
965          */
966         public static final String XML_TAG_IDENTITY = "Identity";
967         public static final String XML_TAG_ANON_IDENTITY = "AnonIdentity";
968         public static final String XML_TAG_PASSWORD = "Password";
969         public static final String XML_TAG_CLIENT_CERT = "ClientCert";
970         public static final String XML_TAG_CA_CERT = "CaCert";
971         public static final String XML_TAG_SUBJECT_MATCH = "SubjectMatch";
972         public static final String XML_TAG_ENGINE = "Engine";
973         public static final String XML_TAG_ENGINE_ID = "EngineId";
974         public static final String XML_TAG_PRIVATE_KEY_ID = "PrivateKeyId";
975         public static final String XML_TAG_ALT_SUBJECT_MATCH = "AltSubjectMatch";
976         public static final String XML_TAG_DOM_SUFFIX_MATCH = "DomSuffixMatch";
977         public static final String XML_TAG_CA_PATH = "CaPath";
978         public static final String XML_TAG_EAP_METHOD = "EapMethod";
979         public static final String XML_TAG_PHASE2_METHOD = "Phase2Method";
980         public static final String XML_TAG_PLMN = "PLMN";
981         public static final String XML_TAG_REALM = "Realm";
982 
983         /**
984          * Write the WifiEnterpriseConfig data elements from the provided config to the XML
985          * stream.
986          *
987          * @param out              XmlSerializer instance pointing to the XML stream.
988          * @param enterpriseConfig WifiEnterpriseConfig object to be serialized.
989          */
writeToXml(XmlSerializer out, WifiEnterpriseConfig enterpriseConfig)990         public static void writeToXml(XmlSerializer out, WifiEnterpriseConfig enterpriseConfig)
991                 throws XmlPullParserException, IOException {
992             XmlUtil.writeNextValue(out, XML_TAG_IDENTITY,
993                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.IDENTITY_KEY));
994             XmlUtil.writeNextValue(out, XML_TAG_ANON_IDENTITY,
995                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY));
996             XmlUtil.writeNextValue(out, XML_TAG_PASSWORD,
997                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY));
998             XmlUtil.writeNextValue(out, XML_TAG_CLIENT_CERT,
999                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY));
1000             XmlUtil.writeNextValue(out, XML_TAG_CA_CERT,
1001                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_CERT_KEY));
1002             XmlUtil.writeNextValue(out, XML_TAG_SUBJECT_MATCH,
1003                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY));
1004             XmlUtil.writeNextValue(out, XML_TAG_ENGINE,
1005                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_KEY));
1006             XmlUtil.writeNextValue(out, XML_TAG_ENGINE_ID,
1007                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY));
1008             XmlUtil.writeNextValue(out, XML_TAG_PRIVATE_KEY_ID,
1009                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY));
1010             XmlUtil.writeNextValue(out, XML_TAG_ALT_SUBJECT_MATCH,
1011                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY));
1012             XmlUtil.writeNextValue(out, XML_TAG_DOM_SUFFIX_MATCH,
1013                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY));
1014             XmlUtil.writeNextValue(out, XML_TAG_CA_PATH,
1015                     enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CA_PATH_KEY));
1016             XmlUtil.writeNextValue(out, XML_TAG_EAP_METHOD, enterpriseConfig.getEapMethod());
1017             XmlUtil.writeNextValue(out, XML_TAG_PHASE2_METHOD, enterpriseConfig.getPhase2Method());
1018             XmlUtil.writeNextValue(out, XML_TAG_PLMN, enterpriseConfig.getPlmn());
1019             XmlUtil.writeNextValue(out, XML_TAG_REALM, enterpriseConfig.getRealm());
1020         }
1021 
1022         /**
1023          * Parses the data elements from the provided XML stream to a WifiEnterpriseConfig object.
1024          *
1025          * @param in            XmlPullParser instance pointing to the XML stream.
1026          * @param outerTagDepth depth of the outer tag in the XML document.
1027          * @return WifiEnterpriseConfig object if parsing is successful, null otherwise.
1028          */
parseFromXml(XmlPullParser in, int outerTagDepth)1029         public static WifiEnterpriseConfig parseFromXml(XmlPullParser in, int outerTagDepth)
1030                 throws XmlPullParserException, IOException {
1031             WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
1032 
1033             // Loop through and parse out all the elements from the stream within this section.
1034             while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
1035                 String[] valueName = new String[1];
1036                 Object value = XmlUtil.readCurrentValue(in, valueName);
1037                 if (valueName[0] == null) {
1038                     throw new XmlPullParserException("Missing value name");
1039                 }
1040                 switch (valueName[0]) {
1041                     case XML_TAG_IDENTITY:
1042                         enterpriseConfig.setFieldValue(
1043                                 WifiEnterpriseConfig.IDENTITY_KEY, (String) value);
1044                         break;
1045                     case XML_TAG_ANON_IDENTITY:
1046                         enterpriseConfig.setFieldValue(
1047                                 WifiEnterpriseConfig.ANON_IDENTITY_KEY, (String) value);
1048                         break;
1049                     case XML_TAG_PASSWORD:
1050                         enterpriseConfig.setFieldValue(
1051                                 WifiEnterpriseConfig.PASSWORD_KEY, (String) value);
1052                         break;
1053                     case XML_TAG_CLIENT_CERT:
1054                         enterpriseConfig.setFieldValue(
1055                                 WifiEnterpriseConfig.CLIENT_CERT_KEY, (String) value);
1056                         break;
1057                     case XML_TAG_CA_CERT:
1058                         enterpriseConfig.setFieldValue(
1059                                 WifiEnterpriseConfig.CA_CERT_KEY, (String) value);
1060                         break;
1061                     case XML_TAG_SUBJECT_MATCH:
1062                         enterpriseConfig.setFieldValue(
1063                                 WifiEnterpriseConfig.SUBJECT_MATCH_KEY, (String) value);
1064                         break;
1065                     case XML_TAG_ENGINE:
1066                         enterpriseConfig.setFieldValue(
1067                                 WifiEnterpriseConfig.ENGINE_KEY, (String) value);
1068                         break;
1069                     case XML_TAG_ENGINE_ID:
1070                         enterpriseConfig.setFieldValue(
1071                                 WifiEnterpriseConfig.ENGINE_ID_KEY, (String) value);
1072                         break;
1073                     case XML_TAG_PRIVATE_KEY_ID:
1074                         enterpriseConfig.setFieldValue(
1075                                 WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, (String) value);
1076                         break;
1077                     case XML_TAG_ALT_SUBJECT_MATCH:
1078                         enterpriseConfig.setFieldValue(
1079                                 WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, (String) value);
1080                         break;
1081                     case XML_TAG_DOM_SUFFIX_MATCH:
1082                         enterpriseConfig.setFieldValue(
1083                                 WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, (String) value);
1084                         break;
1085                     case XML_TAG_CA_PATH:
1086                         enterpriseConfig.setFieldValue(
1087                                 WifiEnterpriseConfig.CA_PATH_KEY, (String) value);
1088                         break;
1089                     case XML_TAG_EAP_METHOD:
1090                         enterpriseConfig.setEapMethod((int) value);
1091                         break;
1092                     case XML_TAG_PHASE2_METHOD:
1093                         enterpriseConfig.setPhase2Method((int) value);
1094                         break;
1095                     case XML_TAG_PLMN:
1096                         enterpriseConfig.setPlmn((String) value);
1097                         break;
1098                     case XML_TAG_REALM:
1099                         enterpriseConfig.setRealm((String) value);
1100                         break;
1101                     default:
1102                         throw new XmlPullParserException(
1103                                 "Unknown value name found: " + valueName[0]);
1104                 }
1105             }
1106             return enterpriseConfig;
1107         }
1108     }
1109 }
1110 
1111