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

Commit e482d456 authored by James Lin's avatar James Lin Committed by Gerrit Code Review
Browse files

Merge "[RCS UCE] The impelementation of parsing the pidf and convert to RcsContactUceCapability"

parents aa18ca8c 7e6f165a
Loading
Loading
Loading
Loading
+39 −2
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

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

import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.IOException;
@@ -35,13 +38,47 @@ public abstract class ElementBase {
    protected abstract String initNamespace();
    protected abstract String initElementName();

    protected String getNamespace() {
    /**
     * @return The namespace of this element
     */
    public String getNamespace() {
        return mNamespace;
    }

    protected String getElementName() {
    /**
     * @return The name of this element.
     */
    public String getElementName() {
        return mElementName;
    }

    public abstract void serialize(XmlSerializer serializer) throws IOException;

    public abstract void parse(XmlPullParser parser) throws IOException, XmlPullParserException;

    protected boolean verifyParsingElement(String namespace, String elementName) {
        if (!getNamespace().equals(namespace) || !getElementName().equals(elementName)) {
            return false;
        } else {
            return true;
        }
    }

    // Move to the end tag of this element
    protected void moveToElementEndTag(XmlPullParser parser, int type)
            throws IOException, XmlPullParserException {
        int eventType = type;

        // Move to the end tag of this element.
        while(!(eventType == XmlPullParser.END_TAG
                && getNamespace().equals(parser.getNamespace())
                && getElementName().equals(parser.getName()))) {
            eventType = parser.next();

            // Leave directly if the event type is the end of the document.
            if (eventType == XmlPullParser.END_DOCUMENT) {
                return;
            }
        }
    }
}
+166 −17
Original line number Diff line number Diff line
@@ -16,25 +16,43 @@

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

import android.net.Uri;
import android.telephony.ims.RcsContactPresenceTuple;
import android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsContactUceCapability.PresenceBuilder;
import android.text.TextUtils;
import android.util.Log;

import com.android.ims.rcs.uce.presence.pidfparser.capabilities.Audio;
import com.android.ims.rcs.uce.presence.pidfparser.capabilities.CapsConstant;
import com.android.ims.rcs.uce.presence.pidfparser.capabilities.Duplex;
import com.android.ims.rcs.uce.presence.pidfparser.capabilities.ServiceCaps;
import com.android.ims.rcs.uce.presence.pidfparser.capabilities.Video;
import com.android.ims.rcs.uce.presence.pidfparser.omapres.OmaPresConstant;
import com.android.ims.rcs.uce.presence.pidfparser.pidf.Basic;
import com.android.ims.rcs.uce.presence.pidfparser.pidf.PidfConstant;
import com.android.ims.rcs.uce.presence.pidfparser.pidf.Presence;
import com.android.ims.rcs.uce.presence.pidfparser.pidf.Tuple;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;

import java.io.IOException;
import java.io.StringWriter;

/**
 * The pidf parser class
 * Convert between the class RcsContactUceCapability and the pidf format.
 */
public class PidfParser {

    private static final String LOG_TAG = "PidfParser";

    /**
     * Convert the RcsContactUceCapability to the string of pidf.
     */
@@ -52,7 +70,7 @@ public class PidfParser {
            serializer.setPrefix("caps", CapsConstant.NAMESPACE);

            // Get the Presence element
            Presence presence = getPresence(capabilities);
            Presence presence = PidfParserUtils.getPresence(capabilities);

            // Start serializing.
            serializer.startDocument(PidfParserConstant.ENCODING_UTF_8, true);
@@ -70,21 +88,152 @@ public class PidfParser {
        return pidfWriter.toString();
    }

    private static Presence getPresence(RcsContactUceCapability capabilities) {
        // Create "presence" element which is the root element of the pidf
        Presence presence = new Presence(capabilities);
    /**
     * Convert the pidf data to the class RcsContactUceCapability.
     */
    public static RcsContactUceCapability convertToRcsContactUceCapability(String pidf) {
        if (TextUtils.isEmpty(pidf)) {
            return null;
        }

        Reader reader = null;
        try {
            // Init the instance of the parser
            XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
            reader = new StringReader(pidf);
            parser.setInput(reader);

            // Start parsing
            Presence presence = parsePidf(parser);

        // Add the Capabilities discovery via Presence tuple.
        Tuple capsDiscoveryTuple = TupleFactory.getCapabilityDiscoveryTuple(capabilities);
        if (capsDiscoveryTuple != null) {
            presence.addTuple(capsDiscoveryTuple);
            // Convert to the class RcsContactUceCapability
            return convert(presence);

        } catch (XmlPullParserException | IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    private static Presence parsePidf(XmlPullParser parser) throws IOException,
            XmlPullParserException {
        Presence presence = null;

        // Add the VoLTE voice/video tuple.
        Tuple ipCallTuple = TupleFactory.getIpCallTuple(capabilities);
        if (ipCallTuple != null) {
            presence.addTuple(ipCallTuple);
        int nextType = parser.next();
        do {
            // Find the Presence start tag
            if (nextType == XmlPullParser.START_TAG
                    && Presence.ELEMENT_NAME.equals(parser.getName())) {
                presence = new Presence();
                presence.parse(parser);
                break;
            }
            nextType = parser.next();
        } while(nextType != XmlPullParser.END_DOCUMENT);

        return presence;
    }

    private static RcsContactUceCapability convert(Presence presence) {
        if (presence == null) {
            return null;
        }

        PresenceBuilder builder = new PresenceBuilder(Uri.parse(presence.getEntity()),
                RcsContactUceCapability.SOURCE_TYPE_NETWORK,
                RcsContactUceCapability.REQUEST_RESULT_FOUND);

        List<Tuple> tupleList = presence.getTupleList();
        if (tupleList == null || tupleList.isEmpty()) {
            Log.w(LOG_TAG, "convert: tuple list is empty");
            return builder.build();
        }

        for (Tuple tuple : tupleList) {
            RcsContactPresenceTuple capabilityTuple = getRcsContactPresenceTuple(tuple);
            if (capabilityTuple != null) {
                builder.addCapabilityTuple(capabilityTuple);
            }
        }
        return builder.build();
    }

    // Get the RcsContactPresenceTuple from the giving tuple element.
    private static RcsContactPresenceTuple getRcsContactPresenceTuple(Tuple tuple) {
        if (tuple == null) {
            return null;
        }

        String status = RcsContactPresenceTuple.TUPLE_BASIC_STATUS_CLOSED;
        if (Basic.OPEN.equals(PidfParserUtils.getTupleStatus(tuple))) {
            status = RcsContactPresenceTuple.TUPLE_BASIC_STATUS_OPEN;
        }

        String serviceId = PidfParserUtils.getTupleServiceId(tuple);
        String serviceVersion = PidfParserUtils.getTupleServiceVersion(tuple);
        String description = PidfParserUtils.getTupleServiceDescription(tuple);

        RcsContactPresenceTuple.Builder builder = new RcsContactPresenceTuple.Builder(status,
                serviceId, serviceVersion);

        // Contact information
        String contact = PidfParserUtils.getTupleContact(tuple);
        if (!TextUtils.isEmpty(contact)) {
            builder.addContactUri(Uri.parse(contact));
        }

        // Service description
        if (!TextUtils.isEmpty(description)) {
            builder.addDescription(description);
        }

        // Service capabilities
        ServiceCaps serviceCaps = tuple.getServiceCaps();
        if (serviceCaps != null) {
            List<ElementBase> serviceCapsList = serviceCaps.getElements();
            if (serviceCapsList != null && !serviceCapsList.isEmpty()) {
                boolean isAudioSupported = false;
                boolean isVideoSupported = false;
                List<String> supportedTypes = null;
                List<String> notSupportedTypes = null;

                for (ElementBase element : serviceCapsList) {
                    if (element instanceof Audio) {
                        isAudioSupported = ((Audio) element).isAudioSupported();
                    } else if (element instanceof Video) {
                        isVideoSupported = ((Video) element).isVideoSupported();
                    } else if (element instanceof Duplex) {
                        supportedTypes = ((Duplex) element).getSupportedTypes();
                        notSupportedTypes = ((Duplex) element).getNotSupportedTypes();
                    }
                }

                ServiceCapabilities.Builder capabilitiesBuilder
                        = new ServiceCapabilities.Builder(isAudioSupported, isVideoSupported);

                if (supportedTypes != null && !supportedTypes.isEmpty()) {
                    for (String supportedType : supportedTypes) {
                        capabilitiesBuilder.addSupportedDuplexMode(supportedType);
                    }
                }

                if (notSupportedTypes != null && !notSupportedTypes.isEmpty()) {
                    for (String notSupportedType : supportedTypes) {
                        capabilitiesBuilder.addUnsupportedDuplexMode(notSupportedType);
                    }
                }
                builder.addServiceCapabilities(capabilitiesBuilder.build());
            }
        }
        return builder.build();
    }
}
+273 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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

import android.net.Uri;
import android.telephony.ims.RcsContactPresenceTuple;
import android.telephony.ims.RcsContactPresenceTuple.BasicStatus;
import android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities;
import android.telephony.ims.RcsContactUceCapability;
import android.text.TextUtils;

import com.android.ims.rcs.uce.presence.pidfparser.capabilities.Audio;
import com.android.ims.rcs.uce.presence.pidfparser.capabilities.Duplex;
import com.android.ims.rcs.uce.presence.pidfparser.capabilities.ServiceCaps;
import com.android.ims.rcs.uce.presence.pidfparser.capabilities.Video;
import com.android.ims.rcs.uce.presence.pidfparser.omapres.Description;
import com.android.ims.rcs.uce.presence.pidfparser.omapres.ServiceDescription;
import com.android.ims.rcs.uce.presence.pidfparser.omapres.ServiceId;
import com.android.ims.rcs.uce.presence.pidfparser.omapres.Version;
import com.android.ims.rcs.uce.presence.pidfparser.pidf.Basic;
import com.android.ims.rcs.uce.presence.pidfparser.pidf.Contact;
import com.android.ims.rcs.uce.presence.pidfparser.pidf.Presence;
import com.android.ims.rcs.uce.presence.pidfparser.pidf.Status;
import com.android.ims.rcs.uce.presence.pidfparser.pidf.Timestamp;
import com.android.ims.rcs.uce.presence.pidfparser.pidf.Tuple;

import java.util.List;

public class PidfParserUtils {
    /**
     * Convert the giving class RcsContactUceCapability to the class Presence.
     */
    static Presence getPresence(RcsContactUceCapability capabilities) {
        // Create "presence" element which is the root element of the pidf
        Presence presence = new Presence(capabilities.getContactUri());

        List<RcsContactPresenceTuple> tupleList = capabilities.getPresenceTuples();
        if (tupleList == null || tupleList.isEmpty()) {
            return presence;
        }

        for (RcsContactPresenceTuple presenceTuple : tupleList) {
            Tuple tupleElement = getTupleElement(presenceTuple);
            if (tupleElement != null) {
                presence.addTuple(tupleElement);
            }
        }

        return presence;
    }

    /**
     * Convert the class from RcsContactPresenceTuple to the class Tuple
     */
    private static Tuple getTupleElement(RcsContactPresenceTuple presenceTuple) {
        if (presenceTuple == null) {
            return null;
        }
        Tuple tupleElement = new Tuple();

        // status element
        handleTupleStatusElement(tupleElement, presenceTuple.getStatus());

        // service description element
        handleTupleServiceDescriptionElement(tupleElement, presenceTuple.getServiceId(),
                presenceTuple.getServiceVersion(), presenceTuple.getServiceDescription());

        // service capabilities element
        handleServiceCapsElement(tupleElement, presenceTuple.getServiceCapabilities());

        // contact element
        handleTupleContactElement(tupleElement, presenceTuple.getContactUri());

        return tupleElement;
    }

    private static void handleTupleContactElement(Tuple tupleElement, Uri uri) {
        if (uri == null) {
            return;
        }
        Contact contactElement = new Contact();
        contactElement.setContact(uri.toString());
        tupleElement.setContact(contactElement);
    }

    private static void handleTupleStatusElement(Tuple tupleElement, @BasicStatus String status) {
        if (TextUtils.isEmpty(status)) {
            return;
        }
        Basic basicElement = new Basic(status);
        Status statusElement = new Status();
        statusElement.setBasic(basicElement);
        tupleElement.setStatus(statusElement);
    }

    private static void handleTupleServiceDescriptionElement(Tuple tupleElement, String serviceId,
            String version, String description) {
        ServiceId serviceIdElement = null;
        Version versionElement = null;
        Description descriptionElement = null;

        // init serviceId element
        if (!TextUtils.isEmpty(serviceId)) {
            serviceIdElement = new ServiceId(serviceId);
        }

        // init version element
        if (!TextUtils.isEmpty(version)) {
            String[] versionAry = version.split("\\.");
            if (versionAry != null && versionAry.length == 2) {
                int majorVersion = Integer.parseInt(versionAry[0]);
                int minorVersion = Integer.parseInt(versionAry[1]);
                versionElement = new Version(majorVersion, minorVersion);
            }
        }

        // init description element
        if (!TextUtils.isEmpty(description)) {
            descriptionElement = new Description(description);
        }

        // Add the Service Description element into the tuple
        if (serviceIdElement != null && versionElement != null && descriptionElement != null) {
            ServiceDescription serviceDescription = new ServiceDescription();
            serviceDescription.setServiceId(serviceIdElement);
            serviceDescription.setVersion(versionElement);
            serviceDescription.setDescription(descriptionElement);
            tupleElement.setServiceDescription(serviceDescription);
        }
    }

    private static void handleServiceCapsElement(Tuple tupleElement,
            ServiceCapabilities serviceCaps) {
        if (serviceCaps == null) {
            return;
        }

        ServiceCaps servCapsElement = new ServiceCaps();

        // Audio and Video element
        Audio audioElement = new Audio(serviceCaps.isAudioCapable());
        Video videoElement = new Video(serviceCaps.isVideoCapable());
        servCapsElement.addElement(audioElement);
        servCapsElement.addElement(videoElement);

        // Duplex element
        List<String> supportedDuplexModes = serviceCaps.getSupportedDuplexModes();
        List<String> UnsupportedDuplexModes = serviceCaps.getUnsupportedDuplexModes();
        if (supportedDuplexModes != null && !supportedDuplexModes.isEmpty() &&
                UnsupportedDuplexModes != null && !UnsupportedDuplexModes.isEmpty()) {
            Duplex duplex = new Duplex();
            if (!supportedDuplexModes.isEmpty()) {
                duplex.addSupportedType(supportedDuplexModes.get(0));
            }
            if (!UnsupportedDuplexModes.isEmpty()) {
                duplex.addSupportedType(UnsupportedDuplexModes.get(0));
            }
            servCapsElement.addElement(duplex);
        }

        tupleElement.setServiceCaps(servCapsElement);
    }

    /**
     * Get the status from the giving tuple.
     */
    public static String getTupleStatus(Tuple tuple) {
        if (tuple == null) {
            return null;
        }
        Status status = tuple.getStatus();
        if (status != null) {
            Basic basic = status.getBasic();
            if (basic != null) {
                return basic.getValue();
            }
        }
        return null;
    }

    /**
     * Get the service Id from the giving tuple.
     */
    public static String getTupleServiceId(Tuple tuple) {
        if (tuple == null) {
            return null;
        }
        ServiceDescription servDescription = tuple.getServiceDescription();
        if (servDescription != null) {
            ServiceId serviceId = servDescription.getServiceId();
            if (serviceId != null) {
                return serviceId.getValue();
            }
        }
        return null;
    }

    /**
     * Get the service version from the giving tuple.
     */
    public static String getTupleServiceVersion(Tuple tuple) {
        if (tuple == null) {
            return null;
        }
        ServiceDescription servDescription = tuple.getServiceDescription();
        if (servDescription != null) {
            Version version = servDescription.getVersion();
            if (version != null) {
                return version.getValue();
            }
        }
        return null;
    }

    /**
     * Get the service description from the giving tuple.
     */
    public static String getTupleServiceDescription(Tuple tuple) {
        if (tuple == null) {
            return null;
        }
        ServiceDescription servDescription = tuple.getServiceDescription();
        if (servDescription != null) {
            Description description = servDescription.getDescription();
            if (description != null) {
                return description.getValue();
            }
        }
        return null;
    }

    /**
     * Get the contact from the giving tuple.
     */
    public static String getTupleContact(Tuple tuple) {
        if (tuple == null) {
            return null;
        }
        Contact contact = tuple.getContact();
        if (contact != null) {
            return contact.getContact();
        }
        return null;
    }

    /**
     * Get the timestamp from the giving tuple.
     */
    public static String getTupleTimestamp(Tuple tuple) {
        if (tuple == null) {
            return null;
        }
        Timestamp timestamp = tuple.getTimestamp();
        if (timestamp != null) {
            return timestamp.getValue();
        }
        return null;
    }
}
+0 −130

File deleted.

Preview size limit exceeded, changes collapsed.

+38 −4
Original line number Diff line number Diff line
@@ -16,8 +16,12 @@

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

import android.text.TextUtils;

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

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.IOException;
@@ -26,8 +30,14 @@ import java.io.IOException;
 * The "audio" element of the Capabilities namespace.
 */
public class Audio extends ElementBase {
    /** The name of this element */
    public static final String ELEMENT_NAME = "audio";

    private boolean mSupported;

    public Audio() {
    }

    public Audio(boolean supported) {
        mSupported = supported;
    }
@@ -39,7 +49,11 @@ public class Audio extends ElementBase {

    @Override
    protected String initElementName() {
        return "audio";
        return ELEMENT_NAME;
    }

    public boolean isAudioSupported() {
        return mSupported;
    }

    @Override
@@ -47,11 +61,31 @@ public class Audio extends ElementBase {
        String namespace = getNamespace();
        String elementName = getElementName();
        serializer.startTag(namespace, elementName);
        serializer.text(getValue());
        serializer.text(String.valueOf(isAudioSupported()));
        serializer.endTag(namespace, elementName);
    }

    private String getValue() {
        return (mSupported) ? "true" : "false";
    @Override
    public void parse(XmlPullParser parser) throws IOException, XmlPullParserException {
        String namespace = parser.getNamespace();
        String name = parser.getName();

        if (!verifyParsingElement(namespace, name)) {
            throw new XmlPullParserException("Incorrect element: " + namespace + ", " + name);
        }

        // Move to the next event to get the value.
        int eventType = parser.next();

        // Get the value if the event type is text.
        if (eventType == XmlPullParser.TEXT) {
            String isSupported = parser.getText();
            if (!TextUtils.isEmpty(isSupported)) {
                mSupported = Boolean.parseBoolean(isSupported);
            }
        }

        // Move to the end tag.
        moveToElementEndTag(parser, eventType);
    }
}
Loading