aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames.cf Lin <jamescflin@google.com>2021-06-02 21:42:28 +0800
committerJames.cf Lin <jamescflin@google.com>2021-06-02 21:53:46 +0800
commit3808616ef55e642e440f27c90892c11f8e4f4f4b (patch)
tree4e4ff23315f8569c3c29cad3d811e6aa6be7ed71
parentec617e6c7bf785debbcfc39368b162a25999ce89 (diff)
downloadims-3808616ef55e642e440f27c90892c11f8e4f4f4b.tar.gz
Fix the PIDF parser may fail when the pidf xml contains the newline characters.
Bug: 186075898 Test: atest PidfParserTest; atest ImsServiceTest Change-Id: Ie54f0d37a0118fa2ed96717942d0cae60254d3ff
-rw-r--r--src/java/com/android/ims/rcs/uce/presence/pidfparser/PidfParser.java15
-rw-r--r--tests/src/com/android/ims/rcs/uce/presence/pidfparser/PidfParserTest.java144
2 files changed, 158 insertions, 1 deletions
diff --git a/src/java/com/android/ims/rcs/uce/presence/pidfparser/PidfParser.java b/src/java/com/android/ims/rcs/uce/presence/pidfparser/PidfParser.java
index 774a48e6..2660f1d9 100644
--- a/src/java/com/android/ims/rcs/uce/presence/pidfparser/PidfParser.java
+++ b/src/java/com/android/ims/rcs/uce/presence/pidfparser/PidfParser.java
@@ -45,6 +45,8 @@ import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -58,6 +60,8 @@ public class PidfParser {
private static final String LOG_TAG = UceUtils.getLogPrefix() + "PidfParser";
+ private static final Pattern PIDF_PATTERN = Pattern.compile("\t|\r|\n");
+
/**
* Convert the RcsContactUceCapability to the string of pidf.
*/
@@ -98,6 +102,15 @@ public class PidfParser {
*/
public static @Nullable RcsContactUceCapability getRcsContactUceCapability(String pidf) {
if (TextUtils.isEmpty(pidf)) {
+ Log.w(LOG_TAG, "getRcsContactUceCapability: The given pidf is empty");
+ return null;
+ }
+
+ // Filter the newline characters
+ Matcher matcher = PIDF_PATTERN.matcher(pidf);
+ String formattedPidf = matcher.replaceAll("");
+ if (TextUtils.isEmpty(formattedPidf)) {
+ Log.w(LOG_TAG, "getRcsContactUceCapability: The formatted pidf is empty");
return null;
}
@@ -106,7 +119,7 @@ public class PidfParser {
// Init the instance of the parser
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
- reader = new StringReader(pidf);
+ reader = new StringReader(formattedPidf);
parser.setInput(reader);
// Start parsing
diff --git a/tests/src/com/android/ims/rcs/uce/presence/pidfparser/PidfParserTest.java b/tests/src/com/android/ims/rcs/uce/presence/pidfparser/PidfParserTest.java
index 73581eea..41f0a3ad 100644
--- a/tests/src/com/android/ims/rcs/uce/presence/pidfparser/PidfParserTest.java
+++ b/tests/src/com/android/ims/rcs/uce/presence/pidfparser/PidfParserTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.net.Uri;
import android.telephony.ims.RcsContactPresenceTuple;
@@ -34,6 +35,7 @@ import androidx.test.filters.SmallTest;
import com.android.ims.ImsTestBase;
import java.time.Instant;
+import java.util.ArrayList;
import java.util.List;
import org.junit.After;
@@ -109,6 +111,93 @@ public class PidfParserTest extends ImsTestBase {
@Test
@SmallTest
+ public void testConvertFromNewlineIncludedPidfToRcsContactUceCapability() throws Exception {
+ final String contact = "tel:+11234567890";
+
+ final RcsContactPresenceTuple.Builder tuple1Builder = new RcsContactPresenceTuple.Builder(
+ "open",
+ "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcse.dp",
+ "1.0");
+ tuple1Builder.setServiceDescription("DiscoveryPresence")
+ .setContactUri(Uri.parse(contact));
+
+ final RcsContactPresenceTuple.Builder tuple2Builder = new RcsContactPresenceTuple.Builder(
+ "open",
+ "org.openmobilealliance:StandaloneMsg",
+ "2.0");
+ tuple2Builder.setServiceDescription("StandaloneMsg")
+ .setContactUri(Uri.parse(contact));
+
+ final RcsContactPresenceTuple.Builder tuple3Builder = new RcsContactPresenceTuple.Builder(
+ "open",
+ "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.mmtel",
+ "1.0");
+ tuple3Builder.setServiceDescription("VoLTE service");
+ ServiceCapabilities.Builder capBuilder = new ServiceCapabilities.Builder(true, true);
+ tuple3Builder.setServiceCapabilities(capBuilder.build())
+ .setContactUri(Uri.parse(contact));
+
+ final List<RcsContactPresenceTuple> expectedTupleList = new ArrayList<>(3);
+ expectedTupleList.add(tuple1Builder.build());
+ expectedTupleList.add(tuple2Builder.build());
+ expectedTupleList.add(tuple3Builder.build());
+
+ // Create the newline included PIDF data
+ String pidfData = getPidfDataWithNewlineCharacters(contact);
+
+ // Convert to the class RcsContactUceCapability
+ RcsContactUceCapability capabilities = PidfParser.getRcsContactUceCapability(pidfData);
+
+ assertNotNull(capabilities);
+ assertEquals(Uri.parse(contact), capabilities.getContactUri());
+ assertEquals(RcsContactUceCapability.SOURCE_TYPE_NETWORK, capabilities.getSourceType());
+ assertEquals(RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE,
+ capabilities.getCapabilityMechanism());
+
+ List<RcsContactPresenceTuple> presenceTupleList = capabilities.getCapabilityTuples();
+ assertNotNull(presenceTupleList);
+ assertEquals(expectedTupleList.size(), presenceTupleList.size());
+
+ for(RcsContactPresenceTuple tuple : presenceTupleList) {
+ String serviceId = tuple.getServiceId();
+ RcsContactPresenceTuple expectedTuple = findTuple(serviceId, expectedTupleList);
+ if (expectedTuple == null) {
+ fail("The service ID is invalid");
+ }
+
+ assertEquals(expectedTuple.getStatus(), tuple.getStatus());
+ assertEquals(expectedTuple.getServiceVersion(), tuple.getServiceVersion());
+ assertEquals(expectedTuple.getServiceDescription(), tuple.getServiceDescription());
+ assertEquals(expectedTuple.getTime(), tuple.getTime());
+ assertEquals(expectedTuple.getContactUri(), tuple.getContactUri());
+
+ ServiceCapabilities expectedCap = expectedTuple.getServiceCapabilities();
+ ServiceCapabilities resultCap = tuple.getServiceCapabilities();
+ if (expectedCap != null) {
+ assertNotNull(resultCap);
+ assertEquals(expectedCap.isAudioCapable(), resultCap.isAudioCapable());
+ assertEquals(expectedCap.isVideoCapable(), resultCap.isVideoCapable());
+ } else {
+ assertNull(resultCap);
+ }
+ }
+ }
+
+ private RcsContactPresenceTuple findTuple(String serviceId,
+ List<RcsContactPresenceTuple> expectedTupleList) {
+ if (serviceId == null) {
+ return null;
+ }
+ for (RcsContactPresenceTuple tuple : expectedTupleList) {
+ if (serviceId.equalsIgnoreCase(tuple.getServiceId())) {
+ return tuple;
+ }
+ }
+ return null;
+ }
+
+ @Test
+ @SmallTest
public void testConvertToRcsContactUceCapabilityForMultipleTuples() throws Exception {
final String contact = "sip:+11234567890@test";
final String serviceId1 = "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcse.dp";
@@ -241,6 +330,61 @@ public class PidfParserTest extends ImsTestBase {
return pidfBuilder.toString();
}
+ private String getPidfDataWithNewlineCharacters(String contact) {
+ String pidf = "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" "
+ + "xmlns:op=\"urn:oma:xml:prs:pidf:oma-pres\" "
+ + "xmlns:b=\"urn:ietf:params:xml:ns:pidf:caps\" "
+ + "entity=\"" + contact + "\">\n"
+ // The first tuple
+ + "<tuple id=\"DiscoveryPres\">\n"
+ + "<status>\n"
+ + "<basic>open</basic>\n"
+ + "</status>\n"
+ + "<op:service-description>\n"
+ + "<op:service-id>"
+ + "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcse.dp</op:service-id>\n"
+ + "<op:version>1.0</op:version>\n"
+ + "<op:description>DiscoveryPresence</op:description>\n"
+ + "</op:service-description>\n"
+ + "<contact>tel:+11234567890</contact>\n"
+ + "</tuple>\n"
+ // The second tuple
+ + "<tuple id=\"VoLTE\">\n"
+ + "<status>\n"
+ + "<basic>open</basic>\n"
+ + "</status>\n"
+ + "<b:servcaps>\n"
+ + "<b:audio>true</b:audio>\n"
+ + "<b:video>true</b:video>\n"
+ + "<b:duplex>\n"
+ + "<b:supported>\n"
+ + "<b:full/>\n"
+ + "</b:supported>\n"
+ + "</b:duplex>\n"
+ + "</b:servcaps>\n"
+ + "<op:service-description>\n"
+ + "<op:service-id>org.3gpp.urn:urn-7:3gpp-service.ims.icsi.mmtel</op:service-id>\n"
+ + "<op:version>1.0</op:version>\n"
+ + "<op:description>VoLTE service</op:description>\n"
+ + "</op:service-description>\n"
+ + "<contact>tel:+11234567890</contact>\n"
+ + "</tuple>\n"
+ // The third tuple
+ + "<tuple id=\"StandaloneMsg\">\n"
+ + "<status>\n"
+ + "<basic>open</basic>\n"
+ + "</status>\n"
+ + "<op:service-description>\n"
+ + "<op:service-id>org.openmobilealliance:StandaloneMsg</op:service-id>\n"
+ + "<op:version>2.0</op:version>\n"
+ + "<op:description>StandaloneMsg</op:description>\n"
+ + "</op:service-description>\n"
+ + "<contact>tel:+11234567890</contact>\n"
+ + "</tuple>\n"
+ + "</presence>";
+ return pidf;
+ }
+
private String getPidfDataWithMultiTuples(String contact, String serviceId1,
String serviceDescription1, String serviceId2, String serviceDescription2,
boolean audioSupported, boolean videoSupported) {