/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wifi.hotspot2; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.hotspot2.pps.Credential; import android.net.wifi.hotspot2.pps.HomeSp; import android.net.wifi.hotspot2.pps.Policy; import android.net.wifi.hotspot2.pps.UpdateParameter; import com.android.internal.util.XmlUtils; import com.android.server.wifi.util.XmlUtil; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Utility class for serialize and deserialize Passpoint related configurations to/from XML string. */ public class PasspointXmlUtils { // XML section header tags. private static final String XML_TAG_SECTION_HEADER_HOMESP = "HomeSP"; private static final String XML_TAG_SECTION_HEADER_CREDENTIAL = "Credential"; private static final String XML_TAG_SECTION_HEADER_USER_CREDENTIAL = "UserCredential"; private static final String XML_TAG_SECTION_HEADER_CERT_CREDENTIAL = "CertCredential"; private static final String XML_TAG_SECTION_HEADER_SIM_CREDENTIAL = "SimCredential"; private static final String XML_TAG_SECTION_HEADER_POLICY = "Policy"; private static final String XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST = "RoamingPartnerList"; private static final String XML_TAG_SECTION_HEADER_ROAMING_PARTNER = "RoamingPartner"; private static final String XML_TAG_SECTION_HEADER_POLICY_UPDATE = "PolicyUpdate"; private static final String XML_TAG_SECTION_HEADER_SUBSCRIPTION_UPDATE = "SubscriptionUpdate"; private static final String XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP = "RequiredProtoPortMap"; private static final String XML_TAG_SECTION_HEADER_PROTO_PORT = "ProtoPort"; // XML value tags. private static final String XML_TAG_FQDN = "FQDN"; private static final String XML_TAG_FRIENDLY_NAME = "FriendlyName"; private static final String XML_TAG_ICON_URL = "IconURL"; private static final String XML_TAG_HOME_NETWORK_IDS = "HomeNetworkIDs"; private static final String XML_TAG_MATCH_ALL_OIS = "MatchAllOIs"; private static final String XML_TAG_MATCH_ANY_OIS = "MatchAnyOIs"; private static final String XML_TAG_OTHER_HOME_PARTNERS = "OtherHomePartners"; private static final String XML_TAG_ROAMING_CONSORTIUM_OIS = "RoamingConsortiumOIs"; private static final String XML_TAG_CREATION_TIME = "CreationTime"; private static final String XML_TAG_EXPIRATION_TIME = "ExpirationTime"; private static final String XML_TAG_REALM = "Realm"; private static final String XML_TAG_CHECK_AAA_SERVER_CERT_STATUS = "CheckAAAServerCertStatus"; private static final String XML_TAG_USERNAME = "Username"; private static final String XML_TAG_PASSWORD = "Password"; private static final String XML_TAG_MACHINE_MANAGED = "MachineManaged"; private static final String XML_TAG_SOFT_TOKEN_APP = "SoftTokenApp"; private static final String XML_TAG_ABLE_TO_SHARE = "AbleToShare"; private static final String XML_TAG_EAP_TYPE = "EAPType"; private static final String XML_TAG_NON_EAP_INNER_METHOD = "NonEAPInnerMethod"; private static final String XML_TAG_CERT_TYPE = "CertType"; private static final String XML_TAG_CERT_SHA256_FINGERPRINT = "CertSHA256Fingerprint"; private static final String XML_TAG_IMSI = "IMSI"; private static final String XML_TAG_MIN_HOME_DOWNLINK_BANDWIDTH = "MinHomeDownlinkBandwidth"; private static final String XML_TAG_MIN_HOME_UPLINK_BANDWIDTH = "MinHomeUplinkBandwidth"; private static final String XML_TAG_MIN_ROAMING_DOWNLINK_BANDWIDTH = "MinRoamingDownlinkBandwidth"; private static final String XML_TAG_MIN_ROAMING_UPLINK_BANDWIDTH = "MinRoamingUplinkBandwidth"; private static final String XML_TAG_EXCLUDED_SSID_LIST = "ExcludedSSIDList"; private static final String XML_TAG_PROTO = "Proto"; private static final String XML_TAG_PORTS = "Ports"; private static final String XML_TAG_MAXIMUM_BSS_LOAD_VALUE = "MaximumBSSLoadValue"; private static final String XML_TAG_FQDN_EXACT_MATCH = "FQDNExactMatch"; private static final String XML_TAG_PRIORITY = "Priority"; private static final String XML_TAG_COUNTRIES = "Countries"; private static final String XML_TAG_UPDATE_INTERVAL = "UpdateInterval"; private static final String XML_TAG_UPDATE_METHOD = "UpdateMethod"; private static final String XML_TAG_RESTRICTION = "Restriction"; private static final String XML_TAG_SERVER_URI = "ServerURI"; private static final String XML_TAG_TRUST_ROOT_CERT_URL = "TrustRootCertURL"; private static final String XML_TAG_TRUST_ROOT_CERT_SHA256_FINGERPRINT = "TrustRootCertSHA256Fingerprint"; private static final String XML_TAG_TRUST_ROOT_CERT_LIST = "TrustRootCertList"; private static final String XML_TAG_UPDATE_IDENTIFIER = "UpdateIdentifier"; private static final String XML_TAG_CREDENTIAL_PRIORITY = "CredentialPriority"; private static final String XML_TAG_SUBSCRIPTION_CREATION_TIME = "SubscriptionCreationTime"; private static final String XML_TAG_SUBSCRIPTION_EXPIRATION_TIME = "SubscriptionExpirationTime"; private static final String XML_TAG_SUBSCRIPTION_TYPE = "SubscriptionType"; private static final String XML_TAG_USAGE_LIMIT_TIME_PERIOD = "UsageLimitTimePeriod"; private static final String XML_TAG_USAGE_LIMIT_START_TIME = "UsageLimitStartTime"; private static final String XML_TAG_USAGE_LIMIT_DATA_LIMIT = "UsageLimitDataLimit"; private static final String XML_TAG_USAGE_LIMIT_TIME_LIMIT = "UsageLimitTimeLimit"; /** * Serialize a {@link PasspointConfiguration} to the output stream as a XML block. * * @param out The output stream to serialize to * @param config The configuration to serialize * @throws XmlPullParserException * @throws IOException */ public static void serializePasspointConfiguration(XmlSerializer out, PasspointConfiguration config) throws XmlPullParserException, IOException { XmlUtil.writeNextValue(out, XML_TAG_UPDATE_IDENTIFIER, config.getUpdateIdentifier()); XmlUtil.writeNextValue(out, XML_TAG_CREDENTIAL_PRIORITY, config.getCredentialPriority()); XmlUtil.writeNextValue(out, XML_TAG_TRUST_ROOT_CERT_LIST, config.getTrustRootCertList()); XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_CREATION_TIME, config.getSubscriptionCreationTimeInMillis()); XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_EXPIRATION_TIME, config.getSubscriptionExpirationTimeInMillis()); XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_TYPE, config.getSubscriptionType()); XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_TIME_PERIOD, config.getUsageLimitUsageTimePeriodInMinutes()); XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_START_TIME, config.getUsageLimitStartTimeInMillis()); XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_DATA_LIMIT, config.getUsageLimitDataLimit()); XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_TIME_LIMIT, config.getUsageLimitTimeLimitInMinutes()); serializeHomeSp(out, config.getHomeSp()); serializeCredential(out, config.getCredential()); serializePolicy(out, config.getPolicy()); serializeUpdateParameter(out, XML_TAG_SECTION_HEADER_SUBSCRIPTION_UPDATE, config.getSubscriptionUpdate()); } /** * Deserialize a {@link PasspointConfiguration} from an input stream containing XML block. * * @param in The input stream to read from * @param outerTagDepth The tag depth of the current XML section * @return {@link PasspointConfiguration} * @throws XmlPullParserException * @throws IOException */ public static PasspointConfiguration deserializePasspointConfiguration(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { PasspointConfiguration config = new PasspointConfiguration(); while (XmlUtils.nextElementWithin(in, outerTagDepth)) { if (isValueElement(in)) { // Value elements. String[] name = new String[1]; Object value = XmlUtil.readCurrentValue(in, name); switch (name[0]) { case XML_TAG_UPDATE_IDENTIFIER: config.setUpdateIdentifier((int) value); break; case XML_TAG_CREDENTIAL_PRIORITY: config.setCredentialPriority((int) value); break; case XML_TAG_TRUST_ROOT_CERT_LIST: config.setTrustRootCertList((Map) value); break; case XML_TAG_SUBSCRIPTION_CREATION_TIME: config.setSubscriptionCreationTimeInMillis((long) value); break; case XML_TAG_SUBSCRIPTION_EXPIRATION_TIME: config.setSubscriptionExpirationTimeInMillis((long) value); break; case XML_TAG_SUBSCRIPTION_TYPE: config.setSubscriptionType((String) value); break; case XML_TAG_USAGE_LIMIT_TIME_PERIOD: config.setUsageLimitUsageTimePeriodInMinutes((long) value); break; case XML_TAG_USAGE_LIMIT_START_TIME: config.setUsageLimitStartTimeInMillis((long) value); break; case XML_TAG_USAGE_LIMIT_DATA_LIMIT: config.setUsageLimitDataLimit((long) value); break; case XML_TAG_USAGE_LIMIT_TIME_LIMIT: config.setUsageLimitTimeLimitInMinutes((long) value); break; default: throw new XmlPullParserException("Unknown value under " + "PasspointConfiguration: " + in.getName()); } } else { // Section elements. switch (in.getName()) { case XML_TAG_SECTION_HEADER_HOMESP: config.setHomeSp(deserializeHomeSP(in, outerTagDepth + 1)); break; case XML_TAG_SECTION_HEADER_CREDENTIAL: config.setCredential(deserializeCredential(in, outerTagDepth + 1)); break; case XML_TAG_SECTION_HEADER_POLICY: config.setPolicy(deserializePolicy(in, outerTagDepth + 1)); break; case XML_TAG_SECTION_HEADER_SUBSCRIPTION_UPDATE: config.setSubscriptionUpdate( deserializeUpdateParameter(in, outerTagDepth + 1)); break; default: throw new XmlPullParserException("Unknown section under " + "PasspointConfiguration: " + in.getName()); } } } return config; } /** * Serialize a {@link HomeSp} to an output stream as a XML block. * * @param out The output stream to serialize data to * @param homeSp The {@link HomeSp} to serialize * @throws XmlPullParserException * @throws IOException */ private static void serializeHomeSp(XmlSerializer out, HomeSp homeSp) throws XmlPullParserException, IOException { if (homeSp == null) { return; } XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_HOMESP); XmlUtil.writeNextValue(out, XML_TAG_FQDN, homeSp.getFqdn()); XmlUtil.writeNextValue(out, XML_TAG_FRIENDLY_NAME, homeSp.getFriendlyName()); XmlUtil.writeNextValue(out, XML_TAG_ICON_URL, homeSp.getIconUrl()); XmlUtil.writeNextValue(out, XML_TAG_HOME_NETWORK_IDS, homeSp.getHomeNetworkIds()); XmlUtil.writeNextValue(out, XML_TAG_MATCH_ALL_OIS, homeSp.getMatchAllOis()); XmlUtil.writeNextValue(out, XML_TAG_MATCH_ANY_OIS, homeSp.getMatchAnyOis()); XmlUtil.writeNextValue(out, XML_TAG_OTHER_HOME_PARTNERS, homeSp.getOtherHomePartners()); XmlUtil.writeNextValue(out, XML_TAG_ROAMING_CONSORTIUM_OIS, homeSp.getRoamingConsortiumOis()); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_HOMESP); } /** * Serialize a {@link Credential} to an output stream as a XML block. * * @param out The output stream to serialize to * @param credential The {@link Credential} to serialize * @throws XmlPullParserException * @throws IOException */ private static void serializeCredential(XmlSerializer out, Credential credential) throws XmlPullParserException, IOException { if (credential == null) { return; } XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_CREDENTIAL); XmlUtil.writeNextValue(out, XML_TAG_CREATION_TIME, credential.getCreationTimeInMillis()); XmlUtil.writeNextValue(out, XML_TAG_EXPIRATION_TIME, credential.getExpirationTimeInMillis()); XmlUtil.writeNextValue(out, XML_TAG_REALM, credential.getRealm()); XmlUtil.writeNextValue(out, XML_TAG_CHECK_AAA_SERVER_CERT_STATUS, credential.getCheckAaaServerCertStatus()); serializeUserCredential(out, credential.getUserCredential()); serializeCertCredential(out, credential.getCertCredential()); serializeSimCredential(out, credential.getSimCredential()); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_CREDENTIAL); } /** * Serialize a {@link Policy} to an output stream as a XML block. * * @param out The output stream to serialize to * @param policy The {@link Policy} to serialize * @throws XmlPullParserException * @throws IOException */ private static void serializePolicy(XmlSerializer out, Policy policy) throws XmlPullParserException, IOException { if (policy == null) { return; } XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_POLICY); XmlUtil.writeNextValue(out, XML_TAG_MIN_HOME_DOWNLINK_BANDWIDTH, policy.getMinHomeDownlinkBandwidth()); XmlUtil.writeNextValue(out, XML_TAG_MIN_HOME_UPLINK_BANDWIDTH, policy.getMinHomeUplinkBandwidth()); XmlUtil.writeNextValue(out, XML_TAG_MIN_ROAMING_DOWNLINK_BANDWIDTH, policy.getMinRoamingDownlinkBandwidth()); XmlUtil.writeNextValue(out, XML_TAG_MIN_ROAMING_UPLINK_BANDWIDTH, policy.getMinRoamingUplinkBandwidth()); XmlUtil.writeNextValue(out, XML_TAG_EXCLUDED_SSID_LIST, policy.getExcludedSsidList()); XmlUtil.writeNextValue(out, XML_TAG_MAXIMUM_BSS_LOAD_VALUE, policy.getMaximumBssLoadValue()); serializeProtoPortMap(out, policy.getRequiredProtoPortMap()); serializeUpdateParameter(out, XML_TAG_SECTION_HEADER_POLICY_UPDATE, policy.getPolicyUpdate()); serializePreferredRoamingPartnerList(out, policy.getPreferredRoamingPartnerList()); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_POLICY); } /** * Serialize a {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} to an output * stream as a XML block. * * @param out The output stream to serialize data to * @param userCredential The UserCredential to serialize * @throws XmlPullParserException * @throws IOException */ private static void serializeUserCredential(XmlSerializer out, Credential.UserCredential userCredential) throws XmlPullParserException, IOException { if (userCredential == null) { return; } XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_USER_CREDENTIAL); XmlUtil.writeNextValue(out, XML_TAG_USERNAME, userCredential.getUsername()); XmlUtil.writeNextValue(out, XML_TAG_PASSWORD, userCredential.getPassword()); XmlUtil.writeNextValue(out, XML_TAG_MACHINE_MANAGED, userCredential.getMachineManaged()); XmlUtil.writeNextValue(out, XML_TAG_SOFT_TOKEN_APP, userCredential.getSoftTokenApp()); XmlUtil.writeNextValue(out, XML_TAG_ABLE_TO_SHARE, userCredential.getAbleToShare()); XmlUtil.writeNextValue(out, XML_TAG_EAP_TYPE, userCredential.getEapType()); XmlUtil.writeNextValue(out, XML_TAG_NON_EAP_INNER_METHOD, userCredential.getNonEapInnerMethod()); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_USER_CREDENTIAL); } /** * Serialize a {@link android.net.wifi.hotspot2.pps.Credential.CertificateCredential} to an * output stream as a XML block. * * @param out The output stream to serialize data to * @param certCredential The CertificateCredential to serialize * @throws XmlPullParserException * @throws IOException */ private static void serializeCertCredential(XmlSerializer out, Credential.CertificateCredential certCredential) throws XmlPullParserException, IOException { if (certCredential == null) { return; } XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_CERT_CREDENTIAL); XmlUtil.writeNextValue(out, XML_TAG_CERT_TYPE, certCredential.getCertType()); XmlUtil.writeNextValue(out, XML_TAG_CERT_SHA256_FINGERPRINT, certCredential.getCertSha256Fingerprint()); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_CERT_CREDENTIAL); } /** * Serialize a {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} to an * output stream as a XML block. * * @param out The output stream to serialize data to * @param simCredential The SimCredential to serialize * @throws XmlPullParserException * @throws IOException */ private static void serializeSimCredential(XmlSerializer out, Credential.SimCredential simCredential) throws XmlPullParserException, IOException { if (simCredential == null) { return; } XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_SIM_CREDENTIAL); XmlUtil.writeNextValue(out, XML_TAG_IMSI, simCredential.getImsi()); XmlUtil.writeNextValue(out, XML_TAG_EAP_TYPE, simCredential.getEapType()); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_SIM_CREDENTIAL); } /** * Serialize a preferred roaming partner list to an output stream as a XML block. * * @param out The output stream to serialize data to * @param preferredRoamingPartnerList The partner list to serialize * @throws XmlPullParserException * @throws IOException */ private static void serializePreferredRoamingPartnerList(XmlSerializer out, List preferredRoamingPartnerList) throws XmlPullParserException, IOException { if (preferredRoamingPartnerList == null) { return; } XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST); for (Policy.RoamingPartner partner : preferredRoamingPartnerList) { XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_ROAMING_PARTNER); XmlUtil.writeNextValue(out, XML_TAG_FQDN, partner.getFqdn()); XmlUtil.writeNextValue(out, XML_TAG_FQDN_EXACT_MATCH, partner.getFqdnExactMatch()); XmlUtil.writeNextValue(out, XML_TAG_PRIORITY, partner.getPriority()); XmlUtil.writeNextValue(out, XML_TAG_COUNTRIES, partner.getCountries()); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_ROAMING_PARTNER); } XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST); } /** * Serialize a {@link UpdateParameter} to an output stream as a XML block. The * {@link UpdateParameter} are used for describing Subscription Update and Policy Update. * * @param out The output stream to serialize data to * @param type The type the {@link UpdateParameter} is used for * @param param The {@link UpdateParameter} to serialize * @throws XmlPullParserException * @throws IOException */ private static void serializeUpdateParameter(XmlSerializer out, String type, UpdateParameter param) throws XmlPullParserException, IOException { if (param == null) { return; } XmlUtil.writeNextSectionStart(out, type); XmlUtil.writeNextValue(out, XML_TAG_UPDATE_INTERVAL, param.getUpdateIntervalInMinutes()); XmlUtil.writeNextValue(out, XML_TAG_UPDATE_METHOD, param.getUpdateMethod()); XmlUtil.writeNextValue(out, XML_TAG_RESTRICTION, param.getRestriction()); XmlUtil.writeNextValue(out, XML_TAG_SERVER_URI, param.getServerUri()); XmlUtil.writeNextValue(out, XML_TAG_USERNAME, param.getUsername()); XmlUtil.writeNextValue(out, XML_TAG_PASSWORD, param.getBase64EncodedPassword()); XmlUtil.writeNextValue(out, XML_TAG_TRUST_ROOT_CERT_URL, param.getTrustRootCertUrl()); XmlUtil.writeNextValue(out, XML_TAG_TRUST_ROOT_CERT_SHA256_FINGERPRINT, param.getTrustRootCertSha256Fingerprint()); XmlUtil.writeNextSectionEnd(out, type); } /** * Serialize a Protocol-to-Ports map to an output stream as a XML block. We're not able * to use {@link XmlUtil#writeNextValue} to write this map, since that function only works for * maps with String key. * * @param out The output stream to serialize data to * @param protoPortMap The proto port map to serialize * @throws XmlPullParserException * @throws IOException */ private static void serializeProtoPortMap(XmlSerializer out, Map protoPortMap) throws XmlPullParserException, IOException { if (protoPortMap == null) { return; } XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP); for (Map.Entry entry : protoPortMap.entrySet()) { XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PROTO_PORT); XmlUtil.writeNextValue(out, XML_TAG_PROTO, entry.getKey()); XmlUtil.writeNextValue(out, XML_TAG_PORTS, entry.getValue()); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PROTO_PORT); } XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP); } /** * Deserialize a {@link HomeSp} from an input stream. * * @param in The input stream to read data from * @param outerTagDepth The tag depth of the current XML section * @return {@link HomeSp} * @throws XmlPullParserException * @throws IOException */ private static HomeSp deserializeHomeSP(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { HomeSp homeSp = new HomeSp(); while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { String[] valueName = new String[1]; Object value = XmlUtil.readCurrentValue(in, valueName); if (valueName[0] == null) { throw new XmlPullParserException("Missing value name"); } switch (valueName[0]) { case XML_TAG_FQDN: homeSp.setFqdn((String) value); break; case XML_TAG_FRIENDLY_NAME: homeSp.setFriendlyName((String) value); break; case XML_TAG_ICON_URL: homeSp.setIconUrl((String) value); break; case XML_TAG_HOME_NETWORK_IDS: homeSp.setHomeNetworkIds((Map) value); break; case XML_TAG_MATCH_ALL_OIS: homeSp.setMatchAllOis((long[]) value); break; case XML_TAG_MATCH_ANY_OIS: homeSp.setMatchAnyOis((long[]) value); break; case XML_TAG_ROAMING_CONSORTIUM_OIS: homeSp.setRoamingConsortiumOis((long[]) value); break; case XML_TAG_OTHER_HOME_PARTNERS: homeSp.setOtherHomePartners((String[]) value); break; default: throw new XmlPullParserException("Unknown data under HomeSP: " + valueName[0]); } } return homeSp; } /** * Deserialize a {@link Credential} from an input stream. * * @param in The input stream to read data from * @param outerTagDepth The tag depth of the current XML section * @return {@link Credential} * @throws XmlPullParserException * @throws IOException */ private static Credential deserializeCredential(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { Credential credential = new Credential(); while (XmlUtils.nextElementWithin(in, outerTagDepth)) { if (isValueElement(in)) { // Value elements. String[] name = new String[1]; Object value = XmlUtil.readCurrentValue(in, name); switch (name[0]) { case XML_TAG_CREATION_TIME: credential.setCreationTimeInMillis((long) value); break; case XML_TAG_EXPIRATION_TIME: credential.setExpirationTimeInMillis((long) value); break; case XML_TAG_REALM: credential.setRealm((String) value); break; case XML_TAG_CHECK_AAA_SERVER_CERT_STATUS: credential.setCheckAaaServerCertStatus((boolean) value); break; default: throw new XmlPullParserException("Unknown value under Credential: " + name[0]); } } else { // Subsection elements. switch (in.getName()) { case XML_TAG_SECTION_HEADER_USER_CREDENTIAL: credential.setUserCredential( deserializeUserCredential(in, outerTagDepth + 1)); break; case XML_TAG_SECTION_HEADER_CERT_CREDENTIAL: credential.setCertCredential( deserializeCertCredential(in, outerTagDepth + 1)); break; case XML_TAG_SECTION_HEADER_SIM_CREDENTIAL: credential.setSimCredential( deserializeSimCredential(in, outerTagDepth + 1)); break; default: throw new XmlPullParserException("Unknown section under Credential: " + in.getName()); } } } return credential; } /** * Deserialize a {@link Policy} from an input stream. * * @param in The input stream to read data from * @param outerTagDepth The tag depth of the current XML section * @return {@link Policy} * @throws XmlPullParserException * @throws IOException */ private static Policy deserializePolicy(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { Policy policy = new Policy(); while (XmlUtils.nextElementWithin(in, outerTagDepth)) { if (isValueElement(in)) { // Value elements. String[] name = new String[1]; Object value = XmlUtil.readCurrentValue(in, name); switch (name[0]) { case XML_TAG_MIN_HOME_DOWNLINK_BANDWIDTH: policy.setMinHomeDownlinkBandwidth((long) value); break; case XML_TAG_MIN_HOME_UPLINK_BANDWIDTH: policy.setMinHomeUplinkBandwidth((long) value); break; case XML_TAG_MIN_ROAMING_DOWNLINK_BANDWIDTH: policy.setMinRoamingDownlinkBandwidth((long) value); break; case XML_TAG_MIN_ROAMING_UPLINK_BANDWIDTH: policy.setMinRoamingUplinkBandwidth((long) value); break; case XML_TAG_EXCLUDED_SSID_LIST: policy.setExcludedSsidList((String[]) value); break; case XML_TAG_MAXIMUM_BSS_LOAD_VALUE: policy.setMaximumBssLoadValue((int) value); break; } } else { // Subsection elements. switch (in.getName()) { case XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP: policy.setRequiredProtoPortMap( deserializeProtoPortMap(in, outerTagDepth + 1)); break; case XML_TAG_SECTION_HEADER_POLICY_UPDATE: policy.setPolicyUpdate(deserializeUpdateParameter(in, outerTagDepth + 1)); break; case XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST: policy.setPreferredRoamingPartnerList( deserializePreferredRoamingPartnerList(in, outerTagDepth + 1)); break; default: throw new XmlPullParserException("Unknown section under Policy: " + in.getName()); } } } return policy; } /** * Deserialize a {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} from an * input stream. * * @param in The input stream to read data from * @param outerTagDepth The tag depth of the current XML section * @return {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} * @throws XmlPullParserException * @throws IOException */ private static Credential.UserCredential deserializeUserCredential(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { Credential.UserCredential userCredential = new Credential.UserCredential(); while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { String[] valueName = new String[1]; Object value = XmlUtil.readCurrentValue(in, valueName); if (valueName[0] == null) { throw new XmlPullParserException("Missing value name"); } switch (valueName[0]) { case XML_TAG_USERNAME: userCredential.setUsername((String) value); break; case XML_TAG_PASSWORD: userCredential.setPassword((String) value); break; case XML_TAG_MACHINE_MANAGED: userCredential.setMachineManaged((boolean) value); break; case XML_TAG_SOFT_TOKEN_APP: userCredential.setSoftTokenApp((String) value); break; case XML_TAG_ABLE_TO_SHARE: userCredential.setAbleToShare((boolean) value); break; case XML_TAG_EAP_TYPE: userCredential.setEapType((int) value); break; case XML_TAG_NON_EAP_INNER_METHOD: userCredential.setNonEapInnerMethod((String) value); break; default: throw new XmlPullParserException("Unknown value under UserCredential: " + valueName[0]); } } return userCredential; } /** * Deserialize a {@link android.net.wifi.hotspot2.pps.Credential.CertificateCredential} * from an input stream. * * @param in The input stream to read data from * @param outerTagDepth The tag depth of the current XML section * @return {@link android.net.wifi.hotspot2.pps.Credential.CertificateCredential} * @throws XmlPullParserException * @throws IOException */ private static Credential.CertificateCredential deserializeCertCredential(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { String[] valueName = new String[1]; Object value = XmlUtil.readCurrentValue(in, valueName); if (valueName[0] == null) { throw new XmlPullParserException("Missing value name"); } switch (valueName[0]) { case XML_TAG_CERT_TYPE: certCredential.setCertType((String) value); break; case XML_TAG_CERT_SHA256_FINGERPRINT: certCredential.setCertSha256Fingerprint((byte[]) value); break; default: throw new XmlPullParserException("Unknown value under CertCredential: " + valueName[0]); } } return certCredential; } /** * Deserialize a {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} from an * input stream. * * @param in The input stream to read data from * @param outerTagDepth The tag depth of the current XML section * @return {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} * @throws XmlPullParserException * @throws IOException */ private static Credential.SimCredential deserializeSimCredential(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { Credential.SimCredential simCredential = new Credential.SimCredential(); while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { String[] valueName = new String[1]; Object value = XmlUtil.readCurrentValue(in, valueName); if (valueName[0] == null) { throw new XmlPullParserException("Missing value name"); } switch (valueName[0]) { case XML_TAG_IMSI: simCredential.setImsi((String) value); break; case XML_TAG_EAP_TYPE: simCredential.setEapType((int) value); break; default: throw new XmlPullParserException("Unknown value under CertCredential: " + valueName[0]); } } return simCredential; } /** * Deserialize a list of {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} from an * input stream. * * @param in The input stream to read data from * @param outerTagDepth The tag depth of the current XML section * @return List of {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} * @throws XmlPullParserException * @throws IOException */ private static List deserializePreferredRoamingPartnerList( XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { List roamingPartnerList = new ArrayList<>(); while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_ROAMING_PARTNER, outerTagDepth)) { roamingPartnerList.add(deserializeRoamingPartner(in, outerTagDepth + 1)); } return roamingPartnerList; } /** * Deserialize a {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} from an input * stream. * * @param in The input stream to read data from * @param outerTagDepth The tag depth of the current XML section * @return {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} * @throws XmlPullParserException * @throws IOException */ private static Policy.RoamingPartner deserializeRoamingPartner(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { Policy.RoamingPartner partner = new Policy.RoamingPartner(); while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { String[] valueName = new String[1]; Object value = XmlUtil.readCurrentValue(in, valueName); if (valueName[0] == null) { throw new XmlPullParserException("Missing value name"); } switch (valueName[0]) { case XML_TAG_FQDN: partner.setFqdn((String) value); break; case XML_TAG_FQDN_EXACT_MATCH: partner.setFqdnExactMatch((boolean) value); break; case XML_TAG_PRIORITY: partner.setPriority((int) value); break; case XML_TAG_COUNTRIES: partner.setCountries((String) value); break; default: throw new XmlPullParserException("Unknown value under RoamingPartner: " + valueName[0]); } } return partner; } /** * Deserialize a {@link UpdateParameter} from an input stream. * * @param in The input stream to read data from * @param outerTagDepth The tag depth of the current XML section * @return {@link UpdateParameter} * @throws XmlPullParserException * @throws IOException */ private static UpdateParameter deserializeUpdateParameter(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { UpdateParameter param = new UpdateParameter(); while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { String[] valueName = new String[1]; Object value = XmlUtil.readCurrentValue(in, valueName); if (valueName[0] == null) { throw new XmlPullParserException("Missing value name"); } switch (valueName[0]) { case XML_TAG_UPDATE_INTERVAL: param.setUpdateIntervalInMinutes((long) value); break; case XML_TAG_UPDATE_METHOD: param.setUpdateMethod((String) value); break; case XML_TAG_RESTRICTION: param.setRestriction((String) value); break; case XML_TAG_SERVER_URI: param.setServerUri((String) value); break; case XML_TAG_USERNAME: param.setUsername((String) value); break; case XML_TAG_PASSWORD: param.setBase64EncodedPassword((String) value); break; case XML_TAG_TRUST_ROOT_CERT_URL: param.setTrustRootCertUrl((String) value); break; case XML_TAG_TRUST_ROOT_CERT_SHA256_FINGERPRINT: param.setTrustRootCertSha256Fingerprint((byte[]) value); break; default: throw new XmlPullParserException("Unknown value under UpdateParameter: " + valueName[0]); } } return param; } /** * Deserialize a Protocol-Port map from an input stream. * * @param in The input stream to read data from * @param outerTagDepth The tag depth of the current XML section * @return Proocol-Port map * @throws XmlPullParserException * @throws IOException */ private static Map deserializeProtoPortMap(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { Map protoPortMap = new HashMap<>(); while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_PROTO_PORT, outerTagDepth)) { int proto = (int) XmlUtil.readNextValueWithName(in, XML_TAG_PROTO); String ports = (String) XmlUtil.readNextValueWithName(in, XML_TAG_PORTS); protoPortMap.put(proto, ports); } return protoPortMap; } /** * Determine if the current element is a value or a section. The "name" attribute of the * element is used as the indicator, when it is present, the element is considered a value * element. * * Value element: * 12 * * Section element: * * ... * * * @param in XML input stream * @return true if the current element is a value */ private static boolean isValueElement(XmlPullParser in) { return in.getAttributeValue(null, "name") != null; } }