Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46d83edb authored by James.cf Lin's avatar James.cf Lin Committed by Automerger Merge Worker
Browse files

Fix the status of tuple cannot be parsed because there are some whitespace...

Fix the status of tuple cannot be parsed because there are some whitespace characters before the Basic tag am: a73b542c

Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/net/ims/+/1730231

Change-Id: Iea86f7e2a5398114ca83e20dfb63c30ab5f0a7ce
parents 79637da5 a73b542c
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -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
+6 −0
Original line number Diff line number Diff line
@@ -17,8 +17,10 @@
package com.android.ims.rcs.uce.presence.pidfparser.pidf;

import android.annotation.StringDef;
import android.util.Log;

import com.android.ims.rcs.uce.presence.pidfparser.ElementBase;
import com.android.ims.rcs.uce.util.UceUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -32,6 +34,8 @@ import java.lang.annotation.RetentionPolicy;
 * The "basic" element of the pidf.
 */
public class Basic extends ElementBase {
    private static final String LOG_TAG = UceUtils.getLogPrefix() + "Basic";

    /** The name of this element */
    public static final String ELEMENT_NAME = "basic";

@@ -104,6 +108,8 @@ public class Basic extends ElementBase {
            } else {
                mBasic = null;
            }
        } else {
            Log.d(LOG_TAG, "The eventType is not TEXT=" + eventType);
        }

        // Move to the end tag.
+9 −2
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package com.android.ims.rcs.uce.presence.pidfparser.pidf;

import android.util.Log;

import com.android.ims.rcs.uce.presence.pidfparser.ElementBase;
import com.android.ims.rcs.uce.util.UceUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -28,6 +31,8 @@ import java.io.IOException;
 * The "status" element of the pidf.
 */
public class Status extends ElementBase {
    private static final String LOG_TAG = UceUtils.getLogPrefix() + "Status";

    /** The name of this element */
    public static final String ELEMENT_NAME = "status";

@@ -76,14 +81,16 @@ public class Status extends ElementBase {
            throw new XmlPullParserException("Incorrect element: " + namespace + ", " + name);
        }

        // Move to the next event to get the Basic tag.
        int eventType = parser.next();
        // Move to the next tag to get the Basic element.
        int eventType = parser.nextTag();

        // Get the value if the event type is text.
        if (eventType == XmlPullParser.START_TAG) {
            Basic basic = new Basic();
            basic.parse(parser);
            mBasic = basic;
        } else {
            Log.d(LOG_TAG, "The eventType is not START_TAG=" + eventType);
        }

        // Move to the end tag.
+186 −0
Original line number Diff line number Diff line
@@ -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;
@@ -107,6 +109,109 @@ public class PidfParserTest extends ImsTestBase {
        assertFalse(presenceTuple1.getServiceCapabilities().isVideoCapable());
    }

    @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.openmobilealliance:ChatSession",
                "2.0");
        tuple3Builder.setServiceDescription("Session Mode Messaging")
                .setContactUri(Uri.parse(contact));

        final RcsContactPresenceTuple.Builder tuple4Builder = new RcsContactPresenceTuple.Builder(
                "open",
                "org.openmobilealliance:File-Transfer",
                "1.0");
        tuple4Builder.setServiceDescription("File Transfer")
                .setContactUri(Uri.parse(contact));

        final RcsContactPresenceTuple.Builder tuple5Builder = new RcsContactPresenceTuple.Builder(
                "open",
                "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.mmtel",
                "1.0");
        tuple5Builder.setServiceDescription("VoLTE service");
        ServiceCapabilities.Builder capBuilder = new ServiceCapabilities.Builder(true, true);
        tuple5Builder.setServiceCapabilities(capBuilder.build())
                .setContactUri(Uri.parse(contact));

        final List<RcsContactPresenceTuple> expectedTupleList = new ArrayList<>(5);
        expectedTupleList.add(tuple1Builder.build());
        expectedTupleList.add(tuple2Builder.build());
        expectedTupleList.add(tuple3Builder.build());
        expectedTupleList.add(tuple4Builder.build());
        expectedTupleList.add(tuple5Builder.build());

        // Create the newline included PIDF data
        String pidfData = getPidfDataWithNewlineAndWhitespaceCharacters();

        // 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 {
@@ -241,6 +346,87 @@ public class PidfParserTest extends ImsTestBase {
        return pidfBuilder.toString();
    }

    private String getPidfDataWithNewlineAndWhitespaceCharacters() {
        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=\"tel:+11234567890\">\n"
                // Tuple: Discovery
                + "   <tuple id=\"DiscoveryPres\">\n\t"
                + "     <status>\n\t"
                + "       <basic>open</basic>\n\t"
                + "     </status>\n\t"
                + "     <op:service-description>\n\t"
                + "       <op:service-id>org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcse.dp"
                                + "</op:service-id>\n\t"
                + "       <op:version>1.0</op:version>\n\t"
                + "       <op:description>DiscoveryPresence</op:description>\n\t"
                + "     </op:service-description>\n\t"
                + "     <contact>tel:+11234567890</contact>\n\t"
                + "   </tuple>\n\t"
                // Tuple: VoLTE
                + "   <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"
                // Tuple: Standalone Message
                + "   <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"
                // Tuple: Session Mode Message
                + "   <tuple id=\"SessModeMessa\">\n"
                + "     <status>\n"
                + "       <basic>open</basic>\n"
                + "     </status>\n"
                + "     <op:service-description>\n"
                + "       <op:service-id>org.openmobilealliance:ChatSession</op:service-id>\n"
                + "       <op:version>2.0</op:version>\n"
                + "       <op:description>Session Mode Messaging</op:description>\n"
                + "     </op:service-description>\n"
                + "     <contact>tel:+11234567890</contact>\n"
                + "   </tuple>\n"
                // Tuple: File Transfer
                + "   <tuple id=\"FileTransfer\">\n"
                + "     <status>\n"
                + "       <basic>open</basic>\n"
                + "     </status>\n"
                + "     <op:service-description>\n"
                + "       <op:service-id>org.openmobilealliance:File-Transfer</op:service-id>\n"
                + "       <op:version>1.0</op:version>\n"
                + "       <op:description>File Transfer</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) {