diff options
author | samalin <samalin@google.com> | 2021-04-28 14:16:54 +0800 |
---|---|---|
committer | Sama Lin <samalin@google.com> | 2021-05-05 05:54:13 +0000 |
commit | 858a0958c915f9ca0e404311b63335a9c17ac893 (patch) | |
tree | 109240a4baa6bccbdeb55cda00e61054a3fedc07 | |
parent | 485093bb5195950d675d7b83ab69694de4378e56 (diff) | |
download | ImsServiceEntitlement-858a0958c915f9ca0e404311b63335a9c17ac893.tar.gz |
Parse the xml doc for individual AppID
The original node map use the key 'APPLICATION' to store the
attribute set. But 'APPLICATION' be used by multiple AppIDs.
To resolve it by appending the AppID to the map key name.
ex. "APPLICATION" + "_" + "ap2004"
Bug: 170788440
Test: presubmit
Change-Id: Icece770bc53cd4e260f8fc452054677e7bcdddd9
5 files changed, 113 insertions, 42 deletions
diff --git a/src/com/android/ImsServiceEntitlement/WfcActivationApi.java b/src/com/android/ImsServiceEntitlement/WfcActivationApi.java index 17bb589..fb50d76 100644 --- a/src/com/android/ImsServiceEntitlement/WfcActivationApi.java +++ b/src/com/android/ImsServiceEntitlement/WfcActivationApi.java @@ -64,8 +64,8 @@ public class WfcActivationApi { /** * Returns WFC entitlement check result from carrier API (over network), or {@code null} on - * unrecoverable network issue or malformed server response. - * This is blocking call so should not be called on main thread. + * unrecoverable network issue or malformed server response. This is blocking call so should not + * be called on main thread. */ @Nullable public EntitlementResult checkEntitlementStatus() { @@ -79,6 +79,7 @@ public class WfcActivationApi { /** Query for status of {@link AppId#VOWIFI}). */ @VisibleForTesting + @Nullable EntitlementResult voWifiEntitlementStatus() { Log.d(TAG, "voWifiEntitlementStatus subId=" + subId); @@ -99,12 +100,14 @@ public class WfcActivationApi { entitlementXmlDoc = new XmlDoc( serviceEntitlement.queryEntitlementStatus( - ServiceEntitlement.APP_VOWIFI, - request)); + ServiceEntitlement.APP_VOWIFI, request)); // While finishing the initial AuthN, save the token // and to be used next time for fast AuthN. - mCachedAccessToken = entitlementXmlDoc.get( - ResponseXmlNode.TOKEN, ResponseXmlAttributes.TOKEN); + entitlementXmlDoc.get( + ResponseXmlNode.TOKEN, + ResponseXmlAttributes.TOKEN, + ServiceEntitlement.APP_VOWIFI) + .ifPresent(token -> mCachedAccessToken = token); } catch (ServiceEntitlementException e) { Log.e(TAG, "queryEntitlementStatus failed", e); } @@ -112,18 +115,21 @@ public class WfcActivationApi { } private static EntitlementResult toEntitlementResult(XmlDoc doc) { - return EntitlementResult.builder() - .setSuccess(true) - .setVowifiStatus(Ts43VowifiStatus.builder(doc).build()) - .setEmergencyAddressWebUrl( - doc.get( - ResponseXmlNode.APPLICATION, - ResponseXmlAttributes.SERVER_FLOW_URL)) - .setEmergencyAddressWebData( - doc.get( - ResponseXmlNode.APPLICATION, - ResponseXmlAttributes.SERVER_FLOW_USER_DATA)) - .build(); + EntitlementResult.Builder builder = + EntitlementResult.builder() + .setSuccess(true) + .setVowifiStatus(Ts43VowifiStatus.builder(doc).build()); + doc.get( + ResponseXmlNode.APPLICATION, + ResponseXmlAttributes.SERVER_FLOW_URL, + ServiceEntitlement.APP_VOWIFI) + .ifPresent(url -> builder.setEmergencyAddressWebUrl(url)); + doc.get( + ResponseXmlNode.APPLICATION, + ResponseXmlAttributes.SERVER_FLOW_USER_DATA, + ServiceEntitlement.APP_VOWIFI) + .ifPresent(userData -> builder.setEmergencyAddressWebData(userData)); + return builder.build(); } private CarrierConfig getCarrierConfig(Context context) { diff --git a/src/com/android/ImsServiceEntitlement/ts43/Ts43Constants.java b/src/com/android/ImsServiceEntitlement/ts43/Ts43Constants.java index 4e34a08..fe18f4b 100644 --- a/src/com/android/ImsServiceEntitlement/ts43/Ts43Constants.java +++ b/src/com/android/ImsServiceEntitlement/ts43/Ts43Constants.java @@ -38,6 +38,8 @@ public final class Ts43Constants { /** XML attribute name of token. */ public static final String TOKEN = "token"; + /** XML attribute name of application identifier. */ + public static final String APP_ID = "AppID"; /** XML attribute name of entitlement status. */ public static final String ENTITLEMENT_STATUS = "EntitlementStatus"; /** XML attribute name of E911 address status. */ diff --git a/src/com/android/ImsServiceEntitlement/ts43/Ts43VowifiStatus.java b/src/com/android/ImsServiceEntitlement/ts43/Ts43VowifiStatus.java index 38ec6cb..a3b6e7a 100644 --- a/src/com/android/ImsServiceEntitlement/ts43/Ts43VowifiStatus.java +++ b/src/com/android/ImsServiceEntitlement/ts43/Ts43VowifiStatus.java @@ -22,6 +22,7 @@ import com.android.imsserviceentitlement.entitlement.VowifiStatus; import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes; import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode; import com.android.imsserviceentitlement.utils.XmlDoc; +import com.android.libraries.entitlement.ServiceEntitlement; import com.google.auto.value.AutoValue; @@ -96,21 +97,29 @@ public abstract class Ts43VowifiStatus implements VowifiStatus { public static Ts43VowifiStatus.Builder builder(XmlDoc doc) { return builder() .setEntitlementStatus( - Integer.parseInt( - doc.get(ResponseXmlNode.APPLICATION, - ResponseXmlAttributes.ENTITLEMENT_STATUS))) + doc.get(ResponseXmlNode.APPLICATION, + ResponseXmlAttributes.ENTITLEMENT_STATUS, + ServiceEntitlement.APP_VOWIFI) + .map(status -> Integer.parseInt(status)) + .orElse(EntitlementStatus.INCOMPATIBLE)) .setTcStatus( - Integer.parseInt( - doc.get(ResponseXmlNode.APPLICATION, - ResponseXmlAttributes.TC_STATUS))) + doc.get(ResponseXmlNode.APPLICATION, + ResponseXmlAttributes.TC_STATUS, + ServiceEntitlement.APP_VOWIFI) + .map(status -> Integer.parseInt(status)) + .orElse(TcStatus.NOT_REQUIRED)) .setAddrStatus( - Integer.parseInt( - doc.get(ResponseXmlNode.APPLICATION, - ResponseXmlAttributes.ADDR_STATUS))) + doc.get(ResponseXmlNode.APPLICATION, + ResponseXmlAttributes.ADDR_STATUS, + ServiceEntitlement.APP_VOWIFI) + .map(status -> Integer.parseInt(status)) + .orElse(AddrStatus.NOT_REQUIRED)) .setProvStatus( - Integer.parseInt( - doc.get(ResponseXmlNode.APPLICATION, - ResponseXmlAttributes.PROVISION_STATUS))); + doc.get(ResponseXmlNode.APPLICATION, + ResponseXmlAttributes.PROVISION_STATUS, + ServiceEntitlement.APP_VOWIFI) + .map(status -> Integer.parseInt(status)) + .orElse(ProvStatus.NOT_REQUIRED)); } /** Builder of {@link Ts43VowifiStatus}. */ diff --git a/src/com/android/ImsServiceEntitlement/utils/XmlDoc.java b/src/com/android/ImsServiceEntitlement/utils/XmlDoc.java index cc18d22..a21bbe2 100644 --- a/src/com/android/ImsServiceEntitlement/utils/XmlDoc.java +++ b/src/com/android/ImsServiceEntitlement/utils/XmlDoc.java @@ -16,6 +16,9 @@ package com.android.imsserviceentitlement.utils; +import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes.APP_ID; +import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode.APPLICATION; + import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; @@ -35,6 +38,7 @@ import org.xml.sax.SAXException; import java.io.IOException; import java.io.StringReader; import java.util.Map; +import java.util.Optional; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -55,11 +59,14 @@ public class XmlDoc { parseXmlResponse(responseBody); } - /** Returns node value for given node and key, or {@code null} if not found. */ - @Nullable - public String get(String node, String key) { - Map<String, String> paramsMap = nodesMap.get(node); - return paramsMap == null ? null : paramsMap.get(key); + /** Returns param value for given node and key. */ + public Optional<String> get(String node, String key, String appId) { + Map<String, String> paramsMap = nodesMap.get(combineKeyWithAppId(node, appId)); + return Optional.ofNullable(paramsMap == null ? null : paramsMap.get(key)); + } + + private String combineKeyWithAppId(String node, @Nullable String appId) { + return APPLICATION.equals(node) && !TextUtils.isEmpty(appId) ? node + "_" + appId : node; } /** @@ -104,8 +111,9 @@ public class XmlDoc { Map<String, String> paramsMap = new ArrayMap<>(); Element element = (Element) nodeList.item(i); paramsMap.putAll(parseParams(element.getElementsByTagName(NODE_PARM))); - - nodesMap.put(map.item(0).getNodeValue(), paramsMap); + nodesMap.put( + combineKeyWithAppId(map.item(0).getNodeValue(), paramsMap.get(APP_ID)), + paramsMap); } } catch (ParserConfigurationException | IOException | SAXException e) { Log.e(TAG, "Failed to parse XML node. " + e); diff --git a/tests/unittests/src/com/android/imsserviceentitlement/utils/XmlDocTest.java b/tests/unittests/src/com/android/imsserviceentitlement/utils/XmlDocTest.java index b5161c6..986436f 100644 --- a/tests/unittests/src/com/android/imsserviceentitlement/utils/XmlDocTest.java +++ b/tests/unittests/src/com/android/imsserviceentitlement/utils/XmlDocTest.java @@ -88,13 +88,38 @@ public class XmlDocTest { + "</characteristic>" + "</wap-provisioningdoc>"; + // A XML sample with server URL and user data unset. + private static final String AUTH_RESPONSE_XML_4 = + "<wap-provisioningdoc version=\"1.1\">" + + "<characteristic type=\"APPLICATION\">" + + "<parm name=\"AppID\" value=\"ap2004\"/>" + + "<parm name=\"ServiceFlow_URL\" value=\"\"" + + "<parm name=\"ServiceFlow_UserData\" value=\"\"/>" + + "</characteristic>" + + "</wap-provisioningdoc>"; + + // A XML sample with multiple appIDs + private static final String AUTH_RESPONSE_XML_5 = + "<wap-provisioningdoc version=\"1.1\">" + + "<characteristic type=\"APPLICATION\">" + + "<parm name=\"AppID\" value=\"ap2004\"/>" + + "<parm name=\"EntitlementStatus\" value=\"0\"/>" + + "</characteristic>" + + "<characteristic type=\"APPLICATION\">" + + "<parm name=\"AppID\" value=\"ap2005\"/>" + + "<parm name=\"EntitlementStatus\" value=\"1\"/>" + + "</characteristic>" + + "</wap-provisioningdoc>"; + private static final String TOKEN = "kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX"; @Test public void parseAuthenticateResponse() { - assertThat(new XmlDoc(AUTH_RESPONSE_XML).get("TOKEN", "token")).isEqualTo(TOKEN); + XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML); + + assertThat(xmlDoc.get("TOKEN", "token", "ap2004").get()).isEqualTo(TOKEN); // Note "&" in input XML are un-escaped to "&". - assertThat(new XmlDoc(AUTH_RESPONSE_XML).get("APPLICATION", "ServiceFlow_UserData")) + assertThat(xmlDoc.get("APPLICATION", "ServiceFlow_UserData", "ap2004").get()) .isEqualTo("token=Y5vcmc%3D" + "&entitlementStatus=0" + "&protocol=TS43" @@ -106,16 +131,37 @@ public class XmlDocTest { @Test public void parseAuthenticateResponse2() { - assertThat(new XmlDoc(AUTH_RESPONSE_XML_2).get("TOKEN", "token")).isEqualTo(TOKEN); + XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_2); + + assertThat(xmlDoc.get("TOKEN", "token", "ap2004").get()).isEqualTo(TOKEN); // Note the "&" in input XML is kept as is - assertThat(new XmlDoc(AUTH_RESPONSE_XML_2).get("APPLICATION", "ServiceFlow_UserData")) + assertThat(xmlDoc.get("APPLICATION", "ServiceFlow_UserData", "ap2004").get()) .isEqualTo("PostData=U6%2FbQ%2BEP&req_locale=en_US"); } @Test public void parseAuthenticateResponse3() { + XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_3); + // Note the "&amp;" in input XML is un-escaped to "&" - assertThat(new XmlDoc(AUTH_RESPONSE_XML_3).get("APPLICATION", "ServiceFlow_UserData")) + assertThat(xmlDoc.get("APPLICATION", "ServiceFlow_UserData", "ap2004").get()) .isEqualTo("PostData=U6%2FbQ%2BEP&l=en_US"); } + + @Test + public void parseAuthenticateResponse4() { + XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_4); + + assertThat(xmlDoc.get("APPLICATION", "ServiceFlow_URL", "ap2004").isPresent()).isFalse(); + assertThat( + xmlDoc.get("APPLICATION", "ServiceFlow_UserData", "ap2004").isPresent()).isFalse(); + } + + @Test + public void parseAuthenticateResponse5() { + XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_5); + + assertThat(xmlDoc.get("APPLICATION", "EntitlementStatus", "ap2004").get()).isEqualTo("0"); + assertThat(xmlDoc.get("APPLICATION", "EntitlementStatus", "ap2005").get()).isEqualTo("1"); + } } |