1 /* 2 * Copyright (C) 2017 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.hotspot2; 18 19 import android.net.wifi.hotspot2.PasspointConfiguration; 20 import android.net.wifi.hotspot2.pps.Credential; 21 import android.net.wifi.hotspot2.pps.HomeSp; 22 import android.net.wifi.hotspot2.pps.Policy; 23 import android.net.wifi.hotspot2.pps.UpdateParameter; 24 25 import com.android.modules.utils.build.SdkLevel; 26 import com.android.server.wifi.util.XmlUtil; 27 28 import org.xmlpull.v1.XmlPullParser; 29 import org.xmlpull.v1.XmlPullParserException; 30 import org.xmlpull.v1.XmlSerializer; 31 32 import java.io.IOException; 33 import java.util.ArrayList; 34 import java.util.HashMap; 35 import java.util.List; 36 import java.util.Map; 37 38 /** 39 * Utility class for serialize and deserialize Passpoint related configurations to/from XML string. 40 */ 41 public class PasspointXmlUtils { 42 // XML section header tags. 43 private static final String XML_TAG_SECTION_HEADER_HOMESP = "HomeSP"; 44 private static final String XML_TAG_SECTION_HEADER_CREDENTIAL = "Credential"; 45 private static final String XML_TAG_SECTION_HEADER_USER_CREDENTIAL = "UserCredential"; 46 private static final String XML_TAG_SECTION_HEADER_CERT_CREDENTIAL = "CertCredential"; 47 private static final String XML_TAG_SECTION_HEADER_SIM_CREDENTIAL = "SimCredential"; 48 private static final String XML_TAG_SECTION_HEADER_POLICY = "Policy"; 49 private static final String XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST = 50 "RoamingPartnerList"; 51 private static final String XML_TAG_SECTION_HEADER_ROAMING_PARTNER = "RoamingPartner"; 52 private static final String XML_TAG_SECTION_HEADER_POLICY_UPDATE = "PolicyUpdate"; 53 private static final String XML_TAG_SECTION_HEADER_SUBSCRIPTION_UPDATE = "SubscriptionUpdate"; 54 private static final String XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP = 55 "RequiredProtoPortMap"; 56 private static final String XML_TAG_SECTION_HEADER_PROTO_PORT = "ProtoPort"; 57 58 // XML value tags. 59 private static final String XML_TAG_FQDN = "FQDN"; 60 private static final String XML_TAG_FRIENDLY_NAME = "FriendlyName"; 61 private static final String XML_TAG_FRIENDLY_NAME_LIST = "FriendlyNameList"; 62 private static final String XML_TAG_ICON_URL = "IconURL"; 63 private static final String XML_TAG_HOME_NETWORK_IDS = "HomeNetworkIDs"; 64 private static final String XML_TAG_MATCH_ALL_OIS = "MatchAllOIs"; 65 private static final String XML_TAG_MATCH_ANY_OIS = "MatchAnyOIs"; 66 private static final String XML_TAG_OTHER_HOME_PARTNERS = "OtherHomePartners"; 67 private static final String XML_TAG_ROAMING_CONSORTIUM_OIS = "RoamingConsortiumOIs"; 68 private static final String XML_TAG_CREATION_TIME = "CreationTime"; 69 private static final String XML_TAG_EXPIRATION_TIME = "ExpirationTime"; 70 private static final String XML_TAG_REALM = "Realm"; 71 private static final String XML_TAG_CHECK_AAA_SERVER_CERT_STATUS = "CheckAAAServerCertStatus"; 72 private static final String XML_TAG_USERNAME = "Username"; 73 private static final String XML_TAG_PASSWORD = "Password"; 74 private static final String XML_TAG_MACHINE_MANAGED = "MachineManaged"; 75 private static final String XML_TAG_SOFT_TOKEN_APP = "SoftTokenApp"; 76 private static final String XML_TAG_ABLE_TO_SHARE = "AbleToShare"; 77 private static final String XML_TAG_EAP_TYPE = "EAPType"; 78 private static final String XML_TAG_NON_EAP_INNER_METHOD = "NonEAPInnerMethod"; 79 private static final String XML_TAG_CERT_TYPE = "CertType"; 80 private static final String XML_TAG_CERT_SHA256_FINGERPRINT = "CertSHA256Fingerprint"; 81 private static final String XML_TAG_IMSI = "IMSI"; 82 private static final String XML_TAG_MIN_HOME_DOWNLINK_BANDWIDTH = "MinHomeDownlinkBandwidth"; 83 private static final String XML_TAG_MIN_HOME_UPLINK_BANDWIDTH = "MinHomeUplinkBandwidth"; 84 private static final String XML_TAG_MIN_ROAMING_DOWNLINK_BANDWIDTH = 85 "MinRoamingDownlinkBandwidth"; 86 private static final String XML_TAG_MIN_ROAMING_UPLINK_BANDWIDTH = 87 "MinRoamingUplinkBandwidth"; 88 private static final String XML_TAG_EXCLUDED_SSID_LIST = "ExcludedSSIDList"; 89 private static final String XML_TAG_PROTO = "Proto"; 90 private static final String XML_TAG_PORTS = "Ports"; 91 private static final String XML_TAG_MAXIMUM_BSS_LOAD_VALUE = "MaximumBSSLoadValue"; 92 private static final String XML_TAG_FQDN_EXACT_MATCH = "FQDNExactMatch"; 93 private static final String XML_TAG_PRIORITY = "Priority"; 94 private static final String XML_TAG_COUNTRIES = "Countries"; 95 private static final String XML_TAG_UPDATE_INTERVAL = "UpdateInterval"; 96 private static final String XML_TAG_UPDATE_METHOD = "UpdateMethod"; 97 private static final String XML_TAG_RESTRICTION = "Restriction"; 98 private static final String XML_TAG_SERVER_URI = "ServerURI"; 99 private static final String XML_TAG_TRUST_ROOT_CERT_URL = "TrustRootCertURL"; 100 private static final String XML_TAG_TRUST_ROOT_CERT_SHA256_FINGERPRINT = 101 "TrustRootCertSHA256Fingerprint"; 102 private static final String XML_TAG_TRUST_ROOT_CERT_LIST = "TrustRootCertList"; 103 private static final String XML_TAG_UPDATE_IDENTIFIER = "UpdateIdentifier"; 104 private static final String XML_TAG_CREDENTIAL_PRIORITY = "CredentialPriority"; 105 private static final String XML_TAG_SUBSCRIPTION_CREATION_TIME = "SubscriptionCreationTime"; 106 private static final String XML_TAG_SUBSCRIPTION_EXPIRATION_TIME = 107 "SubscriptionExpirationTime"; 108 private static final String XML_TAG_SUBSCRIPTION_TYPE = "SubscriptionType"; 109 private static final String XML_TAG_USAGE_LIMIT_TIME_PERIOD = "UsageLimitTimePeriod"; 110 private static final String XML_TAG_USAGE_LIMIT_START_TIME = "UsageLimitStartTime"; 111 private static final String XML_TAG_USAGE_LIMIT_DATA_LIMIT = "UsageLimitDataLimit"; 112 private static final String XML_TAG_USAGE_LIMIT_TIME_LIMIT = "UsageLimitTimeLimit"; 113 private static final String XML_TAG_CARRIER_ID = "CarrierId"; 114 private static final String XML_TAG_SUBSCRIPTION_ID = "SubscriptionId"; 115 private static final String XML_TAG_IS_AUTO_JOIN = "AutoJoinEnabled"; 116 private static final String XML_TAG_IS_MAC_RANDOMIZATION_ENABLED = "IsMacRandomizationEnabled"; 117 private static final String XML_TAG_METERED_OVERRIDE = "MeteredOverride"; 118 private static final String XML_TAG_IS_CARRIER_MERGED = "IsCarrierMerged"; 119 private static final String XML_TAG_IS_OEM_PAID = "IsOemPaid"; 120 private static final String XML_TAG_IS_OEM_PRIVATE = "IsOemPrivate"; 121 private static final String XML_TAG_DECORATED_IDENTITY_PREFIX = "DecoratedIdentityPrefix"; 122 123 /** 124 * Serialize a {@link PasspointConfiguration} to the output stream as a XML block. 125 * 126 * @param out The output stream to serialize to 127 * @param config The configuration to serialize 128 * @throws XmlPullParserException 129 * @throws IOException 130 */ serializePasspointConfiguration(XmlSerializer out, PasspointConfiguration config)131 public static void serializePasspointConfiguration(XmlSerializer out, 132 PasspointConfiguration config) throws XmlPullParserException, IOException { 133 XmlUtil.writeNextValue(out, XML_TAG_UPDATE_IDENTIFIER, config.getUpdateIdentifier()); 134 XmlUtil.writeNextValue(out, XML_TAG_CREDENTIAL_PRIORITY, config.getCredentialPriority()); 135 XmlUtil.writeNextValue(out, XML_TAG_TRUST_ROOT_CERT_LIST, config.getTrustRootCertList()); 136 XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_CREATION_TIME, 137 config.getSubscriptionCreationTimeInMillis()); 138 XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_EXPIRATION_TIME, 139 config.getSubscriptionExpirationTimeMillis()); 140 XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_TYPE, config.getSubscriptionType()); 141 XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_TIME_PERIOD, 142 config.getUsageLimitUsageTimePeriodInMinutes()); 143 XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_START_TIME, 144 config.getUsageLimitStartTimeInMillis()); 145 XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_DATA_LIMIT, 146 config.getUsageLimitDataLimit()); 147 XmlUtil.writeNextValue(out, XML_TAG_USAGE_LIMIT_TIME_LIMIT, 148 config.getUsageLimitTimeLimitInMinutes()); 149 serializeHomeSp(out, config.getHomeSp()); 150 serializeCredential(out, config.getCredential()); 151 serializePolicy(out, config.getPolicy()); 152 serializeUpdateParameter(out, XML_TAG_SECTION_HEADER_SUBSCRIPTION_UPDATE, 153 config.getSubscriptionUpdate()); 154 if (config.getServiceFriendlyNames() != null) { 155 XmlUtil.writeNextValue(out, XML_TAG_FRIENDLY_NAME_LIST, 156 config.getServiceFriendlyNames()); 157 } 158 XmlUtil.writeNextValue(out, XML_TAG_CARRIER_ID, config.getCarrierId()); 159 XmlUtil.writeNextValue(out, XML_TAG_SUBSCRIPTION_ID, config.getSubscriptionId()); 160 XmlUtil.writeNextValue(out, XML_TAG_IS_AUTO_JOIN, config.isAutojoinEnabled()); 161 XmlUtil.writeNextValue(out, XML_TAG_IS_MAC_RANDOMIZATION_ENABLED, 162 config.isMacRandomizationEnabled()); 163 XmlUtil.writeNextValue(out, XML_TAG_METERED_OVERRIDE, config.getMeteredOverride()); 164 XmlUtil.writeNextValue(out, XML_TAG_IS_CARRIER_MERGED, config.isCarrierMerged()); 165 XmlUtil.writeNextValue(out, XML_TAG_IS_OEM_PAID, config.isOemPaid()); 166 XmlUtil.writeNextValue(out, XML_TAG_IS_OEM_PRIVATE, config.isOemPrivate()); 167 if (SdkLevel.isAtLeastS()) { 168 XmlUtil.writeNextValue(out, XML_TAG_DECORATED_IDENTITY_PREFIX, 169 config.getDecoratedIdentityPrefix()); 170 } 171 } 172 173 /** 174 * Deserialize a {@link PasspointConfiguration} from an input stream containing XML block. 175 * 176 * @param in The input stream to read from 177 * @param outerTagDepth The tag depth of the current XML section 178 * @return {@link PasspointConfiguration} 179 * @throws XmlPullParserException 180 * @throws IOException 181 */ deserializePasspointConfiguration(XmlPullParser in, int outerTagDepth)182 public static PasspointConfiguration deserializePasspointConfiguration(XmlPullParser in, 183 int outerTagDepth) throws XmlPullParserException, IOException { 184 PasspointConfiguration config = new PasspointConfiguration(); 185 while (XmlUtil.nextElementWithin(in, outerTagDepth)) { 186 if (isValueElement(in)) { 187 // Value elements. 188 String[] name = new String[1]; 189 Object value = XmlUtil.readCurrentValue(in, name); 190 switch (name[0]) { 191 case XML_TAG_UPDATE_IDENTIFIER: 192 config.setUpdateIdentifier((int) value); 193 break; 194 case XML_TAG_CREDENTIAL_PRIORITY: 195 config.setCredentialPriority((int) value); 196 break; 197 case XML_TAG_TRUST_ROOT_CERT_LIST: 198 config.setTrustRootCertList((Map<String, byte[]>) value); 199 break; 200 case XML_TAG_SUBSCRIPTION_CREATION_TIME: 201 config.setSubscriptionCreationTimeInMillis((long) value); 202 break; 203 case XML_TAG_SUBSCRIPTION_EXPIRATION_TIME: 204 config.setSubscriptionExpirationTimeInMillis((long) value); 205 break; 206 case XML_TAG_SUBSCRIPTION_TYPE: 207 config.setSubscriptionType((String) value); 208 break; 209 case XML_TAG_USAGE_LIMIT_TIME_PERIOD: 210 config.setUsageLimitUsageTimePeriodInMinutes((long) value); 211 break; 212 case XML_TAG_USAGE_LIMIT_START_TIME: 213 config.setUsageLimitStartTimeInMillis((long) value); 214 break; 215 case XML_TAG_USAGE_LIMIT_DATA_LIMIT: 216 config.setUsageLimitDataLimit((long) value); 217 break; 218 case XML_TAG_USAGE_LIMIT_TIME_LIMIT: 219 config.setUsageLimitTimeLimitInMinutes((long) value); 220 break; 221 case XML_TAG_FRIENDLY_NAME_LIST: 222 config.setServiceFriendlyNames((Map<String, String>) value); 223 break; 224 case XML_TAG_CARRIER_ID: 225 config.setCarrierId((int) value); 226 break; 227 case XML_TAG_SUBSCRIPTION_ID: 228 config.setSubscriptionId((int) value); 229 break; 230 case XML_TAG_IS_AUTO_JOIN: 231 config.setAutojoinEnabled((boolean) value); 232 break; 233 case XML_TAG_IS_MAC_RANDOMIZATION_ENABLED: 234 config.setMacRandomizationEnabled((boolean) value); 235 break; 236 case XML_TAG_METERED_OVERRIDE: 237 config.setMeteredOverride((int) value); 238 break; 239 case XML_TAG_IS_CARRIER_MERGED: 240 config.setCarrierMerged((boolean) value); 241 break; 242 case XML_TAG_IS_OEM_PAID: 243 config.setOemPaid((boolean) value); 244 break; 245 case XML_TAG_IS_OEM_PRIVATE: 246 config.setOemPrivate((boolean) value); 247 break; 248 case XML_TAG_DECORATED_IDENTITY_PREFIX: 249 if (SdkLevel.isAtLeastS()) { 250 config.setDecoratedIdentityPrefix((String) value); 251 } 252 break; 253 default: 254 throw new XmlPullParserException("Unknown value under " 255 + "PasspointConfiguration: " + in.getName()); 256 } 257 } else { 258 // Section elements. 259 switch (in.getName()) { 260 case XML_TAG_SECTION_HEADER_HOMESP: 261 config.setHomeSp(deserializeHomeSP(in, outerTagDepth + 1)); 262 break; 263 case XML_TAG_SECTION_HEADER_CREDENTIAL: 264 config.setCredential(deserializeCredential(in, outerTagDepth + 1)); 265 break; 266 case XML_TAG_SECTION_HEADER_POLICY: 267 config.setPolicy(deserializePolicy(in, outerTagDepth + 1)); 268 break; 269 case XML_TAG_SECTION_HEADER_SUBSCRIPTION_UPDATE: 270 config.setSubscriptionUpdate( 271 deserializeUpdateParameter(in, outerTagDepth + 1)); 272 break; 273 default: 274 throw new XmlPullParserException("Unknown section under " 275 + "PasspointConfiguration: " + in.getName()); 276 } 277 } 278 } 279 return config; 280 } 281 282 /** 283 * Serialize a {@link HomeSp} to an output stream as a XML block. 284 * 285 * @param out The output stream to serialize data to 286 * @param homeSp The {@link HomeSp} to serialize 287 * @throws XmlPullParserException 288 * @throws IOException 289 */ serializeHomeSp(XmlSerializer out, HomeSp homeSp)290 private static void serializeHomeSp(XmlSerializer out, HomeSp homeSp) 291 throws XmlPullParserException, IOException { 292 if (homeSp == null) { 293 return; 294 } 295 XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_HOMESP); 296 XmlUtil.writeNextValue(out, XML_TAG_FQDN, homeSp.getFqdn()); 297 XmlUtil.writeNextValue(out, XML_TAG_FRIENDLY_NAME, homeSp.getFriendlyName()); 298 XmlUtil.writeNextValue(out, XML_TAG_ICON_URL, homeSp.getIconUrl()); 299 XmlUtil.writeNextValue(out, XML_TAG_HOME_NETWORK_IDS, homeSp.getHomeNetworkIds()); 300 XmlUtil.writeNextValue(out, XML_TAG_MATCH_ALL_OIS, homeSp.getMatchAllOis()); 301 XmlUtil.writeNextValue(out, XML_TAG_MATCH_ANY_OIS, homeSp.getMatchAnyOis()); 302 XmlUtil.writeNextValue(out, XML_TAG_OTHER_HOME_PARTNERS, homeSp.getOtherHomePartners()); 303 XmlUtil.writeNextValue(out, XML_TAG_ROAMING_CONSORTIUM_OIS, 304 homeSp.getRoamingConsortiumOis()); 305 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_HOMESP); 306 } 307 308 /** 309 * Serialize a {@link Credential} to an output stream as a XML block. 310 * 311 * @param out The output stream to serialize to 312 * @param credential The {@link Credential} to serialize 313 * @throws XmlPullParserException 314 * @throws IOException 315 */ serializeCredential(XmlSerializer out, Credential credential)316 private static void serializeCredential(XmlSerializer out, Credential credential) 317 throws XmlPullParserException, IOException { 318 if (credential == null) { 319 return; 320 } 321 XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_CREDENTIAL); 322 XmlUtil.writeNextValue(out, XML_TAG_CREATION_TIME, credential.getCreationTimeInMillis()); 323 XmlUtil.writeNextValue(out, XML_TAG_EXPIRATION_TIME, 324 credential.getExpirationTimeInMillis()); 325 XmlUtil.writeNextValue(out, XML_TAG_REALM, credential.getRealm()); 326 XmlUtil.writeNextValue(out, XML_TAG_CHECK_AAA_SERVER_CERT_STATUS, 327 credential.getCheckAaaServerCertStatus()); 328 serializeUserCredential(out, credential.getUserCredential()); 329 serializeCertCredential(out, credential.getCertCredential()); 330 serializeSimCredential(out, credential.getSimCredential()); 331 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_CREDENTIAL); 332 } 333 334 /** 335 * Serialize a {@link Policy} to an output stream as a XML block. 336 * 337 * @param out The output stream to serialize to 338 * @param policy The {@link Policy} to serialize 339 * @throws XmlPullParserException 340 * @throws IOException 341 */ serializePolicy(XmlSerializer out, Policy policy)342 private static void serializePolicy(XmlSerializer out, Policy policy) 343 throws XmlPullParserException, IOException { 344 if (policy == null) { 345 return; 346 } 347 XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_POLICY); 348 XmlUtil.writeNextValue(out, XML_TAG_MIN_HOME_DOWNLINK_BANDWIDTH, 349 policy.getMinHomeDownlinkBandwidth()); 350 XmlUtil.writeNextValue(out, XML_TAG_MIN_HOME_UPLINK_BANDWIDTH, 351 policy.getMinHomeUplinkBandwidth()); 352 XmlUtil.writeNextValue(out, XML_TAG_MIN_ROAMING_DOWNLINK_BANDWIDTH, 353 policy.getMinRoamingDownlinkBandwidth()); 354 XmlUtil.writeNextValue(out, XML_TAG_MIN_ROAMING_UPLINK_BANDWIDTH, 355 policy.getMinRoamingUplinkBandwidth()); 356 XmlUtil.writeNextValue(out, XML_TAG_EXCLUDED_SSID_LIST, policy.getExcludedSsidList()); 357 XmlUtil.writeNextValue(out, XML_TAG_MAXIMUM_BSS_LOAD_VALUE, 358 policy.getMaximumBssLoadValue()); 359 serializeProtoPortMap(out, policy.getRequiredProtoPortMap()); 360 serializeUpdateParameter(out, XML_TAG_SECTION_HEADER_POLICY_UPDATE, 361 policy.getPolicyUpdate()); 362 serializePreferredRoamingPartnerList(out, policy.getPreferredRoamingPartnerList()); 363 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_POLICY); 364 } 365 366 /** 367 * Serialize a {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} to an output 368 * stream as a XML block. 369 * 370 * @param out The output stream to serialize data to 371 * @param userCredential The UserCredential to serialize 372 * @throws XmlPullParserException 373 * @throws IOException 374 */ serializeUserCredential(XmlSerializer out, Credential.UserCredential userCredential)375 private static void serializeUserCredential(XmlSerializer out, 376 Credential.UserCredential userCredential) throws XmlPullParserException, IOException { 377 if (userCredential == null) { 378 return; 379 } 380 XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_USER_CREDENTIAL); 381 XmlUtil.writeNextValue(out, XML_TAG_USERNAME, userCredential.getUsername()); 382 XmlUtil.writeNextValue(out, XML_TAG_PASSWORD, userCredential.getPassword()); 383 XmlUtil.writeNextValue(out, XML_TAG_MACHINE_MANAGED, userCredential.getMachineManaged()); 384 XmlUtil.writeNextValue(out, XML_TAG_SOFT_TOKEN_APP, userCredential.getSoftTokenApp()); 385 XmlUtil.writeNextValue(out, XML_TAG_ABLE_TO_SHARE, userCredential.getAbleToShare()); 386 XmlUtil.writeNextValue(out, XML_TAG_EAP_TYPE, userCredential.getEapType()); 387 XmlUtil.writeNextValue(out, XML_TAG_NON_EAP_INNER_METHOD, 388 userCredential.getNonEapInnerMethod()); 389 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_USER_CREDENTIAL); 390 } 391 392 /** 393 * Serialize a {@link android.net.wifi.hotspot2.pps.Credential.CertificateCredential} to an 394 * output stream as a XML block. 395 * 396 * @param out The output stream to serialize data to 397 * @param certCredential The CertificateCredential to serialize 398 * @throws XmlPullParserException 399 * @throws IOException 400 */ serializeCertCredential(XmlSerializer out, Credential.CertificateCredential certCredential)401 private static void serializeCertCredential(XmlSerializer out, 402 Credential.CertificateCredential certCredential) 403 throws XmlPullParserException, IOException { 404 if (certCredential == null) { 405 return; 406 } 407 XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_CERT_CREDENTIAL); 408 XmlUtil.writeNextValue(out, XML_TAG_CERT_TYPE, certCredential.getCertType()); 409 XmlUtil.writeNextValue(out, XML_TAG_CERT_SHA256_FINGERPRINT, 410 certCredential.getCertSha256Fingerprint()); 411 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_CERT_CREDENTIAL); 412 } 413 414 /** 415 * Serialize a {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} to an 416 * output stream as a XML block. 417 * 418 * @param out The output stream to serialize data to 419 * @param simCredential The SimCredential to serialize 420 * @throws XmlPullParserException 421 * @throws IOException 422 */ serializeSimCredential(XmlSerializer out, Credential.SimCredential simCredential)423 private static void serializeSimCredential(XmlSerializer out, 424 Credential.SimCredential simCredential) throws XmlPullParserException, IOException { 425 if (simCredential == null) { 426 return; 427 } 428 XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_SIM_CREDENTIAL); 429 XmlUtil.writeNextValue(out, XML_TAG_IMSI, simCredential.getImsi()); 430 XmlUtil.writeNextValue(out, XML_TAG_EAP_TYPE, simCredential.getEapType()); 431 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_SIM_CREDENTIAL); 432 } 433 434 /** 435 * Serialize a preferred roaming partner list to an output stream as a XML block. 436 * 437 * @param out The output stream to serialize data to 438 * @param preferredRoamingPartnerList The partner list to serialize 439 * @throws XmlPullParserException 440 * @throws IOException 441 */ serializePreferredRoamingPartnerList(XmlSerializer out, List<Policy.RoamingPartner> preferredRoamingPartnerList)442 private static void serializePreferredRoamingPartnerList(XmlSerializer out, 443 List<Policy.RoamingPartner> preferredRoamingPartnerList) 444 throws XmlPullParserException, IOException { 445 if (preferredRoamingPartnerList == null) { 446 return; 447 } 448 XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST); 449 for (Policy.RoamingPartner partner : preferredRoamingPartnerList) { 450 XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_ROAMING_PARTNER); 451 XmlUtil.writeNextValue(out, XML_TAG_FQDN, partner.getFqdn()); 452 XmlUtil.writeNextValue(out, XML_TAG_FQDN_EXACT_MATCH, partner.getFqdnExactMatch()); 453 XmlUtil.writeNextValue(out, XML_TAG_PRIORITY, partner.getPriority()); 454 XmlUtil.writeNextValue(out, XML_TAG_COUNTRIES, partner.getCountries()); 455 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_ROAMING_PARTNER); 456 } 457 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST); 458 } 459 460 /** 461 * Serialize a {@link UpdateParameter} to an output stream as a XML block. The 462 * {@link UpdateParameter} are used for describing Subscription Update and Policy Update. 463 * 464 * @param out The output stream to serialize data to 465 * @param type The type the {@link UpdateParameter} is used for 466 * @param param The {@link UpdateParameter} to serialize 467 * @throws XmlPullParserException 468 * @throws IOException 469 */ serializeUpdateParameter(XmlSerializer out, String type, UpdateParameter param)470 private static void serializeUpdateParameter(XmlSerializer out, String type, 471 UpdateParameter param) throws XmlPullParserException, IOException { 472 if (param == null) { 473 return; 474 } 475 XmlUtil.writeNextSectionStart(out, type); 476 XmlUtil.writeNextValue(out, XML_TAG_UPDATE_INTERVAL, param.getUpdateIntervalInMinutes()); 477 XmlUtil.writeNextValue(out, XML_TAG_UPDATE_METHOD, param.getUpdateMethod()); 478 XmlUtil.writeNextValue(out, XML_TAG_RESTRICTION, param.getRestriction()); 479 XmlUtil.writeNextValue(out, XML_TAG_SERVER_URI, param.getServerUri()); 480 XmlUtil.writeNextValue(out, XML_TAG_USERNAME, param.getUsername()); 481 XmlUtil.writeNextValue(out, XML_TAG_PASSWORD, param.getBase64EncodedPassword()); 482 XmlUtil.writeNextValue(out, XML_TAG_TRUST_ROOT_CERT_URL, param.getTrustRootCertUrl()); 483 XmlUtil.writeNextValue(out, XML_TAG_TRUST_ROOT_CERT_SHA256_FINGERPRINT, 484 param.getTrustRootCertSha256Fingerprint()); 485 XmlUtil.writeNextSectionEnd(out, type); 486 } 487 488 /** 489 * Serialize a Protocol-to-Ports map to an output stream as a XML block. We're not able 490 * to use {@link XmlUtil#writeNextValue} to write this map, since that function only works for 491 * maps with String key. 492 * 493 * @param out The output stream to serialize data to 494 * @param protoPortMap The proto port map to serialize 495 * @throws XmlPullParserException 496 * @throws IOException 497 */ serializeProtoPortMap(XmlSerializer out, Map<Integer, String> protoPortMap)498 private static void serializeProtoPortMap(XmlSerializer out, Map<Integer, String> protoPortMap) 499 throws XmlPullParserException, IOException { 500 if (protoPortMap == null) { 501 return; 502 } 503 XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP); 504 for (Map.Entry<Integer, String> entry : protoPortMap.entrySet()) { 505 XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PROTO_PORT); 506 XmlUtil.writeNextValue(out, XML_TAG_PROTO, entry.getKey()); 507 XmlUtil.writeNextValue(out, XML_TAG_PORTS, entry.getValue()); 508 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PROTO_PORT); 509 } 510 XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP); 511 } 512 513 /** 514 * Deserialize a {@link HomeSp} from an input stream. 515 * 516 * @param in The input stream to read data from 517 * @param outerTagDepth The tag depth of the current XML section 518 * @return {@link HomeSp} 519 * @throws XmlPullParserException 520 * @throws IOException 521 */ deserializeHomeSP(XmlPullParser in, int outerTagDepth)522 private static HomeSp deserializeHomeSP(XmlPullParser in, int outerTagDepth) 523 throws XmlPullParserException, IOException { 524 HomeSp homeSp = new HomeSp(); 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_FQDN: 533 homeSp.setFqdn((String) value); 534 break; 535 case XML_TAG_FRIENDLY_NAME: 536 homeSp.setFriendlyName((String) value); 537 break; 538 case XML_TAG_ICON_URL: 539 homeSp.setIconUrl((String) value); 540 break; 541 case XML_TAG_HOME_NETWORK_IDS: 542 homeSp.setHomeNetworkIds((Map<String, Long>) value); 543 break; 544 case XML_TAG_MATCH_ALL_OIS: 545 homeSp.setMatchAllOis((long[]) value); 546 break; 547 case XML_TAG_MATCH_ANY_OIS: 548 homeSp.setMatchAnyOis((long[]) value); 549 break; 550 case XML_TAG_ROAMING_CONSORTIUM_OIS: 551 homeSp.setRoamingConsortiumOis((long[]) value); 552 break; 553 case XML_TAG_OTHER_HOME_PARTNERS: 554 homeSp.setOtherHomePartners((String[]) value); 555 break; 556 default: 557 throw new XmlPullParserException("Unknown data under HomeSP: " + valueName[0]); 558 } 559 } 560 return homeSp; 561 } 562 563 /** 564 * Deserialize a {@link Credential} from an input stream. 565 * 566 * @param in The input stream to read data from 567 * @param outerTagDepth The tag depth of the current XML section 568 * @return {@link Credential} 569 * @throws XmlPullParserException 570 * @throws IOException 571 */ deserializeCredential(XmlPullParser in, int outerTagDepth)572 private static Credential deserializeCredential(XmlPullParser in, int outerTagDepth) 573 throws XmlPullParserException, IOException { 574 Credential credential = new Credential(); 575 while (XmlUtil.nextElementWithin(in, outerTagDepth)) { 576 if (isValueElement(in)) { 577 // Value elements. 578 String[] name = new String[1]; 579 Object value = XmlUtil.readCurrentValue(in, name); 580 switch (name[0]) { 581 case XML_TAG_CREATION_TIME: 582 credential.setCreationTimeInMillis((long) value); 583 break; 584 case XML_TAG_EXPIRATION_TIME: 585 credential.setExpirationTimeInMillis((long) value); 586 break; 587 case XML_TAG_REALM: 588 credential.setRealm((String) value); 589 break; 590 case XML_TAG_CHECK_AAA_SERVER_CERT_STATUS: 591 credential.setCheckAaaServerCertStatus((boolean) value); 592 break; 593 default: 594 throw new XmlPullParserException("Unknown value under Credential: " 595 + name[0]); 596 } 597 } else { 598 // Subsection elements. 599 switch (in.getName()) { 600 case XML_TAG_SECTION_HEADER_USER_CREDENTIAL: 601 credential.setUserCredential( 602 deserializeUserCredential(in, outerTagDepth + 1)); 603 break; 604 case XML_TAG_SECTION_HEADER_CERT_CREDENTIAL: 605 credential.setCertCredential( 606 deserializeCertCredential(in, outerTagDepth + 1)); 607 break; 608 case XML_TAG_SECTION_HEADER_SIM_CREDENTIAL: 609 credential.setSimCredential( 610 deserializeSimCredential(in, outerTagDepth + 1)); 611 break; 612 default: 613 throw new XmlPullParserException("Unknown section under Credential: " 614 + in.getName()); 615 } 616 } 617 } 618 return credential; 619 } 620 621 /** 622 * Deserialize a {@link Policy} from an input stream. 623 * 624 * @param in The input stream to read data from 625 * @param outerTagDepth The tag depth of the current XML section 626 * @return {@link Policy} 627 * @throws XmlPullParserException 628 * @throws IOException 629 */ deserializePolicy(XmlPullParser in, int outerTagDepth)630 private static Policy deserializePolicy(XmlPullParser in, int outerTagDepth) 631 throws XmlPullParserException, IOException { 632 Policy policy = new Policy(); 633 while (XmlUtil.nextElementWithin(in, outerTagDepth)) { 634 if (isValueElement(in)) { 635 // Value elements. 636 String[] name = new String[1]; 637 Object value = XmlUtil.readCurrentValue(in, name); 638 switch (name[0]) { 639 case XML_TAG_MIN_HOME_DOWNLINK_BANDWIDTH: 640 policy.setMinHomeDownlinkBandwidth((long) value); 641 break; 642 case XML_TAG_MIN_HOME_UPLINK_BANDWIDTH: 643 policy.setMinHomeUplinkBandwidth((long) value); 644 break; 645 case XML_TAG_MIN_ROAMING_DOWNLINK_BANDWIDTH: 646 policy.setMinRoamingDownlinkBandwidth((long) value); 647 break; 648 case XML_TAG_MIN_ROAMING_UPLINK_BANDWIDTH: 649 policy.setMinRoamingUplinkBandwidth((long) value); 650 break; 651 case XML_TAG_EXCLUDED_SSID_LIST: 652 policy.setExcludedSsidList((String[]) value); 653 break; 654 case XML_TAG_MAXIMUM_BSS_LOAD_VALUE: 655 policy.setMaximumBssLoadValue((int) value); 656 break; 657 } 658 } else { 659 // Subsection elements. 660 switch (in.getName()) { 661 case XML_TAG_SECTION_HEADER_REQUIRED_PROTO_PORT_MAP: 662 policy.setRequiredProtoPortMap( 663 deserializeProtoPortMap(in, outerTagDepth + 1)); 664 break; 665 case XML_TAG_SECTION_HEADER_POLICY_UPDATE: 666 policy.setPolicyUpdate(deserializeUpdateParameter(in, outerTagDepth + 1)); 667 break; 668 case XML_TAG_SECTION_HEADER_PREFERRED_ROAMING_PARTNER_LIST: 669 policy.setPreferredRoamingPartnerList( 670 deserializePreferredRoamingPartnerList(in, outerTagDepth + 1)); 671 break; 672 default: 673 throw new XmlPullParserException("Unknown section under Policy: " 674 + in.getName()); 675 } 676 } 677 } 678 return policy; 679 } 680 681 /** 682 * Deserialize a {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} from an 683 * input stream. 684 * 685 * @param in The input stream to read data from 686 * @param outerTagDepth The tag depth of the current XML section 687 * @return {@link android.net.wifi.hotspot2.pps.Credential.UserCredential} 688 * @throws XmlPullParserException 689 * @throws IOException 690 */ deserializeUserCredential(XmlPullParser in, int outerTagDepth)691 private static Credential.UserCredential deserializeUserCredential(XmlPullParser in, 692 int outerTagDepth) throws XmlPullParserException, IOException { 693 Credential.UserCredential userCredential = new Credential.UserCredential(); 694 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 695 String[] valueName = new String[1]; 696 Object value = XmlUtil.readCurrentValue(in, valueName); 697 if (valueName[0] == null) { 698 throw new XmlPullParserException("Missing value name"); 699 } 700 switch (valueName[0]) { 701 case XML_TAG_USERNAME: 702 userCredential.setUsername((String) value); 703 break; 704 case XML_TAG_PASSWORD: 705 userCredential.setPassword((String) value); 706 break; 707 case XML_TAG_MACHINE_MANAGED: 708 userCredential.setMachineManaged((boolean) value); 709 break; 710 case XML_TAG_SOFT_TOKEN_APP: 711 userCredential.setSoftTokenApp((String) value); 712 break; 713 case XML_TAG_ABLE_TO_SHARE: 714 userCredential.setAbleToShare((boolean) value); 715 break; 716 case XML_TAG_EAP_TYPE: 717 userCredential.setEapType((int) value); 718 break; 719 case XML_TAG_NON_EAP_INNER_METHOD: 720 userCredential.setNonEapInnerMethod((String) value); 721 break; 722 default: 723 throw new XmlPullParserException("Unknown value under UserCredential: " 724 + valueName[0]); 725 } 726 } 727 return userCredential; 728 } 729 730 /** 731 * Deserialize a {@link android.net.wifi.hotspot2.pps.Credential.CertificateCredential} 732 * from an input stream. 733 * 734 * @param in The input stream to read data from 735 * @param outerTagDepth The tag depth of the current XML section 736 * @return {@link android.net.wifi.hotspot2.pps.Credential.CertificateCredential} 737 * @throws XmlPullParserException 738 * @throws IOException 739 */ deserializeCertCredential(XmlPullParser in, int outerTagDepth)740 private static Credential.CertificateCredential deserializeCertCredential(XmlPullParser in, 741 int outerTagDepth) throws XmlPullParserException, IOException { 742 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 743 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 744 String[] valueName = new String[1]; 745 Object value = XmlUtil.readCurrentValue(in, valueName); 746 if (valueName[0] == null) { 747 throw new XmlPullParserException("Missing value name"); 748 } 749 switch (valueName[0]) { 750 case XML_TAG_CERT_TYPE: 751 certCredential.setCertType((String) value); 752 break; 753 case XML_TAG_CERT_SHA256_FINGERPRINT: 754 certCredential.setCertSha256Fingerprint((byte[]) value); 755 break; 756 default: 757 throw new XmlPullParserException("Unknown value under CertCredential: " 758 + valueName[0]); 759 } 760 } 761 return certCredential; 762 } 763 764 /** 765 * Deserialize a {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} from an 766 * input stream. 767 * 768 * @param in The input stream to read data from 769 * @param outerTagDepth The tag depth of the current XML section 770 * @return {@link android.net.wifi.hotspot2.pps.Credential.SimCredential} 771 * @throws XmlPullParserException 772 * @throws IOException 773 */ deserializeSimCredential(XmlPullParser in, int outerTagDepth)774 private static Credential.SimCredential deserializeSimCredential(XmlPullParser in, 775 int outerTagDepth) throws XmlPullParserException, IOException { 776 Credential.SimCredential simCredential = new Credential.SimCredential(); 777 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 778 String[] valueName = new String[1]; 779 Object value = XmlUtil.readCurrentValue(in, valueName); 780 if (valueName[0] == null) { 781 throw new XmlPullParserException("Missing value name"); 782 } 783 switch (valueName[0]) { 784 case XML_TAG_IMSI: 785 simCredential.setImsi((String) value); 786 break; 787 case XML_TAG_EAP_TYPE: 788 simCredential.setEapType((int) value); 789 break; 790 default: 791 throw new XmlPullParserException("Unknown value under CertCredential: " 792 + valueName[0]); 793 } 794 } 795 return simCredential; 796 } 797 798 /** 799 * Deserialize a list of {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} from an 800 * input stream. 801 * 802 * @param in The input stream to read data from 803 * @param outerTagDepth The tag depth of the current XML section 804 * @return List of {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} 805 * @throws XmlPullParserException 806 * @throws IOException 807 */ deserializePreferredRoamingPartnerList( XmlPullParser in, int outerTagDepth)808 private static List<Policy.RoamingPartner> deserializePreferredRoamingPartnerList( 809 XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { 810 List<Policy.RoamingPartner> roamingPartnerList = new ArrayList<>(); 811 while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_ROAMING_PARTNER, 812 outerTagDepth)) { 813 roamingPartnerList.add(deserializeRoamingPartner(in, outerTagDepth + 1)); 814 } 815 return roamingPartnerList; 816 } 817 818 /** 819 * Deserialize a {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} from an input 820 * stream. 821 * 822 * @param in The input stream to read data from 823 * @param outerTagDepth The tag depth of the current XML section 824 * @return {@link android.net.wifi.hotspot2.pps.Policy.RoamingPartner} 825 * @throws XmlPullParserException 826 * @throws IOException 827 */ deserializeRoamingPartner(XmlPullParser in, int outerTagDepth)828 private static Policy.RoamingPartner deserializeRoamingPartner(XmlPullParser in, 829 int outerTagDepth) throws XmlPullParserException, IOException { 830 Policy.RoamingPartner partner = new Policy.RoamingPartner(); 831 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 832 String[] valueName = new String[1]; 833 Object value = XmlUtil.readCurrentValue(in, valueName); 834 if (valueName[0] == null) { 835 throw new XmlPullParserException("Missing value name"); 836 } 837 switch (valueName[0]) { 838 case XML_TAG_FQDN: 839 partner.setFqdn((String) value); 840 break; 841 case XML_TAG_FQDN_EXACT_MATCH: 842 partner.setFqdnExactMatch((boolean) value); 843 break; 844 case XML_TAG_PRIORITY: 845 partner.setPriority((int) value); 846 break; 847 case XML_TAG_COUNTRIES: 848 partner.setCountries((String) value); 849 break; 850 default: 851 throw new XmlPullParserException("Unknown value under RoamingPartner: " 852 + valueName[0]); 853 } 854 } 855 return partner; 856 } 857 858 /** 859 * Deserialize a {@link UpdateParameter} from an input stream. 860 * 861 * @param in The input stream to read data from 862 * @param outerTagDepth The tag depth of the current XML section 863 * @return {@link UpdateParameter} 864 * @throws XmlPullParserException 865 * @throws IOException 866 */ deserializeUpdateParameter(XmlPullParser in, int outerTagDepth)867 private static UpdateParameter deserializeUpdateParameter(XmlPullParser in, 868 int outerTagDepth) throws XmlPullParserException, IOException { 869 UpdateParameter param = new UpdateParameter(); 870 while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 871 String[] valueName = new String[1]; 872 Object value = XmlUtil.readCurrentValue(in, valueName); 873 if (valueName[0] == null) { 874 throw new XmlPullParserException("Missing value name"); 875 } 876 switch (valueName[0]) { 877 case XML_TAG_UPDATE_INTERVAL: 878 param.setUpdateIntervalInMinutes((long) value); 879 break; 880 case XML_TAG_UPDATE_METHOD: 881 param.setUpdateMethod((String) value); 882 break; 883 case XML_TAG_RESTRICTION: 884 param.setRestriction((String) value); 885 break; 886 case XML_TAG_SERVER_URI: 887 param.setServerUri((String) value); 888 break; 889 case XML_TAG_USERNAME: 890 param.setUsername((String) value); 891 break; 892 case XML_TAG_PASSWORD: 893 param.setBase64EncodedPassword((String) value); 894 break; 895 case XML_TAG_TRUST_ROOT_CERT_URL: 896 param.setTrustRootCertUrl((String) value); 897 break; 898 case XML_TAG_TRUST_ROOT_CERT_SHA256_FINGERPRINT: 899 param.setTrustRootCertSha256Fingerprint((byte[]) value); 900 break; 901 default: 902 throw new XmlPullParserException("Unknown value under UpdateParameter: " 903 + valueName[0]); 904 } 905 } 906 return param; 907 } 908 909 /** 910 * Deserialize a Protocol-Port map from an input stream. 911 * 912 * @param in The input stream to read data from 913 * @param outerTagDepth The tag depth of the current XML section 914 * @return Proocol-Port map 915 * @throws XmlPullParserException 916 * @throws IOException 917 */ deserializeProtoPortMap(XmlPullParser in, int outerTagDepth)918 private static Map<Integer, String> deserializeProtoPortMap(XmlPullParser in, 919 int outerTagDepth) throws XmlPullParserException, IOException { 920 Map<Integer, String> protoPortMap = new HashMap<>(); 921 while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_PROTO_PORT, 922 outerTagDepth)) { 923 int proto = (int) XmlUtil.readNextValueWithName(in, XML_TAG_PROTO); 924 String ports = (String) XmlUtil.readNextValueWithName(in, XML_TAG_PORTS); 925 protoPortMap.put(proto, ports); 926 } 927 return protoPortMap; 928 } 929 930 /** 931 * Determine if the current element is a value or a section. The "name" attribute of the 932 * element is used as the indicator, when it is present, the element is considered a value 933 * element. 934 * 935 * Value element: 936 * <int name="test">12</int> 937 * 938 * Section element: 939 * <Test> 940 * ... 941 * </Test> 942 * 943 * @param in XML input stream 944 * @return true if the current element is a value 945 */ isValueElement(XmlPullParser in)946 private static boolean isValueElement(XmlPullParser in) { 947 return in.getAttributeValue(null, "name") != null; 948 } 949 } 950