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