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