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

Commit 685a2fce authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Define new shell commands to get and modify UCE PUBLISH

1) Implement "override-published-caps", which allows a user to add
and remove capabilities from the UCE PUBLISH.
2) Implement "get-last-publish-pidf", which allows a user to get
the last successful PIDF XML or "none" if we are not published.

Bug: 180033898
Test: test commands with "adb shell cmd phone uce ..."
Merged-In: Ifb2125b8f8cf2b85e4efe380ef4b3562abcf3806
Change-Id: Ifb2125b8f8cf2b85e4efe380ef4b3562abcf3806
parent 5c6f9e3c
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Set;

/**
 * The UceController will manage the RCS UCE requests on a per subscription basis. When it receives
@@ -507,6 +508,51 @@ public class UceController {
        return mPublishController.getUcePublishState();
    }

    /**
     * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
     * <p>
     * Used for testing ONLY.
     * @return the new capabilities that will be used for PUBLISH.
     */
    public RcsContactUceCapability addRegistrationOverrideCapabilities(Set<String> featureTags) {
        return mPublishController.addRegistrationOverrideCapabilities(featureTags);
    }

    /**
     * Remove existing feature tags to the Set used to calculate the capabilities in PUBLISH.
     * <p>
     * Used for testing ONLY.
     * @return the new capabilities that will be used for PUBLISH.
     */
    public RcsContactUceCapability removeRegistrationOverrideCapabilities(Set<String> featureTags) {
        return mPublishController.removeRegistrationOverrideCapabilities(featureTags);
    }

    /**
     * Clear all overrides in the Set used to calculate the capabilities in PUBLISH.
     * <p>
     * Used for testing ONLY.
     * @return the new capabilities that will be used for PUBLISH.
     */
    public RcsContactUceCapability clearRegistrationOverrideCapabilities() {
        return mPublishController.clearRegistrationOverrideCapabilities();
    }

    /**
     * @return current RcsContactUceCapability instance that will be used for PUBLISH.
     */
    public RcsContactUceCapability getLatestRcsContactUceCapability() {
        return mPublishController.getLatestRcsContactUceCapability();
    }

    /**
     * Get the PIDF XML associated with the last successful publish or null if not PUBLISHed to the
     * network.
     */
    public String getLastPidfXml() {
        return mPublishController.getLastPidfXml();
    }

    /**
     * Get the subscription ID.
     */
+112 −18
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ import android.telephony.ims.RcsContactUceCapability.OptionsBuilder;
import android.telephony.ims.RcsContactUceCapability.PresenceBuilder;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities;
import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Log;

import com.android.ims.rcs.uce.util.FeatureTags;
@@ -36,6 +38,7 @@ import com.android.ims.rcs.uce.util.UceUtils;
import com.android.internal.util.IndentingPrintWriter;

import java.io.PrintWriter;
import java.util.Collections;
import java.util.Set;

/**
@@ -46,9 +49,25 @@ public class DeviceCapabilityInfo {

    private final int mSubId;

    private final LocalLog mLocalLog = new LocalLog(UceUtils.LOG_SIZE);

    // Tracks capability status based on the IMS registration.
    private final PublishServiceDescTracker mServiceCapRegTracker;

    // FT overrides to add to the IMS registration, which will be added to the existing
    // capabilities.
    private final Set<String> mOverrideAddFeatureTags = new ArraySet<>();

    // FT overrides to remove from the existing IMS registration, which will remove the related
    // capabilities.
    private final Set<String> mOverrideRemoveFeatureTags = new ArraySet<>();

    // The feature tags associated with the last IMS registration update.
    private Set<String> mLastRegistrationFeatureTags = Collections.emptySet();
    // The feature tags associated with the last IMS registration update, which also include
    // overrides
    private Set<String> mLastRegistrationOverrideFeatureTags = Collections.emptySet();

    // The mmtel feature is registered or not
    private boolean mMmtelRegistered;

@@ -135,34 +154,93 @@ public class DeviceCapabilityInfo {

    /**
     * Update the status that IMS RCS is registered.
     * @return true if the IMS registration status changed, false if it did not.
     */
    public synchronized void updateImsRcsRegistered(ImsRegistrationAttributes attr) {
    public synchronized boolean updateImsRcsRegistered(ImsRegistrationAttributes attr) {
        StringBuilder builder = new StringBuilder();
        builder.append("IMS RCS registered: original state=").append(mRcsRegistered)
                .append(", changes type from ").append(mRcsNetworkRegType)
                .append(" to ").append(attr.getTransportType());
        logi(builder.toString());

        boolean changed = false;
        if (!mRcsRegistered) {
            mRcsRegistered = true;
            changed = true;
        }

        if (mRcsNetworkRegType != attr.getTransportType()) {
            mRcsNetworkRegType = attr.getTransportType();
            changed = true;
        }

        mServiceCapRegTracker.updateImsRegistration(attr.getFeatureTags());
        mLastRegistrationFeatureTags = attr.getFeatureTags();
        changed |= updateRegistration(mLastRegistrationFeatureTags);

        return changed;
    }

    /**
     * Update the status that IMS RCS is unregistered.
     */
    public synchronized void updateImsRcsUnregistered() {
    public synchronized boolean updateImsRcsUnregistered() {
        logi("IMS RCS unregistered: original state=" + mRcsRegistered);
        boolean changed = false;
        if (mRcsRegistered) {
            mRcsRegistered = false;
            changed = true;
        }
        mRcsNetworkRegType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
        return changed;
    }

    public synchronized boolean addRegistrationOverrideCapabilities(Set<String> featureTags) {
        logd("override - add: " + featureTags);
        mOverrideRemoveFeatureTags.removeAll(featureTags);
        mOverrideAddFeatureTags.addAll(featureTags);
        // Call with the last feature tags so that the new ones will be potentially picked up.
        return updateRegistration(mLastRegistrationFeatureTags);
    };

    public synchronized boolean removeRegistrationOverrideCapabilities(Set<String> featureTags) {
        logd("override - remove: " + featureTags);
        mOverrideAddFeatureTags.removeAll(featureTags);
        mOverrideRemoveFeatureTags.addAll(featureTags);
        // Call with the last feature tags so that the new ones will be potentially picked up.
        return updateRegistration(mLastRegistrationFeatureTags);
    };

    public synchronized boolean clearRegistrationOverrideCapabilities() {
        logd("override - clear");
        mOverrideAddFeatureTags.clear();
        mOverrideRemoveFeatureTags.clear();
        // Call with the last feature tags so that base tags will be restored
        return updateRegistration(mLastRegistrationFeatureTags);
    };

    /**
     * Update the IMS registration tracked by the PublishServiceDescTracker if needed.
     * @return true if the registration changed, else otherwise.
     */
    private boolean updateRegistration(Set<String> baseTags) {
        Set<String> updatedTags = updateImsRegistrationFeatureTags(baseTags);
        if (!mLastRegistrationOverrideFeatureTags.equals(updatedTags)) {
            mLastRegistrationOverrideFeatureTags = updatedTags;
            mServiceCapRegTracker.updateImsRegistration(updatedTags);
            return true;
        }
        return false;
    }

    /**
     * Combine IMS registration with overrides to produce a new feature tag Set.
     * @return true if the IMS registration changed, false otherwise.
     */
    private synchronized Set<String> updateImsRegistrationFeatureTags(Set<String> featureTags) {
        Set<String> tags = new ArraySet<>(featureTags);
        tags.addAll(mOverrideAddFeatureTags);
        tags.removeAll(mOverrideRemoveFeatureTags);
        return tags;
    }

    /**
@@ -321,7 +399,8 @@ public class DeviceCapabilityInfo {
                ServiceDescription.SERVICE_DESCRIPTION_MMTEL_VOICE, capableFromReg);
        ServiceDescription vtDescription = getCustomizedDescription(
                ServiceDescription.SERVICE_DESCRIPTION_MMTEL_VOICE_VIDEO, capableFromReg);
        ServiceDescription descToUse = hasVtCapability() ? vtDescription : voiceDescription;
        ServiceDescription descToUse = (hasVolteCapability() && hasVtCapability()) ?
                vtDescription : voiceDescription;
        ServiceCapabilities servCaps = new ServiceCapabilities.Builder(
                hasVolteCapability(), hasVtCapability())
                .addSupportedDuplexMode(ServiceCapabilities.DUPLEX_MODE_FULL).build();
@@ -381,31 +460,39 @@ public class DeviceCapabilityInfo {

    // Check if the device has the VoLTE capability
    private synchronized boolean hasVolteCapability() {
        if (mMmTelCapabilities != null
                && mMmTelCapabilities.isCapable(MmTelCapabilities.CAPABILITY_TYPE_VOICE)) {
            return true;
        }
        return false;
        return overrideCapability(FeatureTags.FEATURE_TAG_MMTEL, mMmTelCapabilities != null
                && mMmTelCapabilities.isCapable(MmTelCapabilities.CAPABILITY_TYPE_VOICE));
    }

    // Check if the device has the VT capability
    private synchronized boolean hasVtCapability() {
        if (mMmTelCapabilities != null
                && mMmTelCapabilities.isCapable(MmTelCapabilities.CAPABILITY_TYPE_VIDEO)) {
            return true;
        }
        return false;
        return overrideCapability(FeatureTags.FEATURE_TAG_VIDEO, mMmTelCapabilities != null
                && mMmTelCapabilities.isCapable(MmTelCapabilities.CAPABILITY_TYPE_VIDEO));
    }

    // Check if the device has the Call Composer capability
    private synchronized boolean hasCallComposerCapability() {
        if (mMmTelCapabilities != null && mMmTelCapabilities.isCapable(
                MmTelCapabilities.CAPABILITY_TYPE_CALL_COMPOSER)) {
            return true;
        return overrideCapability(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY,
                mMmTelCapabilities != null && mMmTelCapabilities.isCapable(
                        MmTelCapabilities.CAPABILITY_TYPE_CALL_COMPOSER));
    }

    /**
     * @return the overridden value for the provided feature tag or the original capability if there
     * is no override.
     */
    private synchronized boolean overrideCapability(String featureTag, boolean originalCap) {
        if (mOverrideRemoveFeatureTags.contains(featureTag)) {
            return false;
        }

        if (mOverrideAddFeatureTags.contains(featureTag)) {
            return true;
        }

        return originalCap;
    }

    private synchronized MmTelCapabilities deepCopyCapabilities(MmTelCapabilities capabilities) {
        MmTelCapabilities mmTelCapabilities = new MmTelCapabilities();
        if (capabilities.isCapable(MmTelCapabilities.CAPABILITY_TYPE_VOICE)) {
@@ -428,14 +515,17 @@ public class DeviceCapabilityInfo {

    private void logd(String log) {
        Log.d(LOG_TAG, getLogPrefix().append(log).toString());
        mLocalLog.log("[D] " + log);
    }

    private void logi(String log) {
        Log.i(LOG_TAG, getLogPrefix().append(log).toString());
        mLocalLog.log("[I] " + log);
    }

    private void logw(String log) {
        Log.w(LOG_TAG, getLogPrefix().append(log).toString());
        mLocalLog.log("[W] " + log);
    }

    private StringBuilder getLogPrefix() {
@@ -450,9 +540,13 @@ public class DeviceCapabilityInfo {
        pw.println("DeviceCapabilityInfo :");
        pw.increaseIndent();

        pw.println("ServiceDescriptionTracker:");
        mServiceCapRegTracker.dump(pw);

        pw.println("Log:");
        pw.increaseIndent();
        mLocalLog.dump(pw);
        pw.decreaseIndent();

        pw.decreaseIndent();
    }
}
+7 −4
Original line number Diff line number Diff line
@@ -580,16 +580,19 @@ public class DeviceCapabilityListener {
     * This method is called when RCS is registered.
     */
    private void handleImsRcsRegistered(ImsRegistrationAttributes attr) {
        mCapabilityInfo.updateImsRcsRegistered(attr);
        if (mCapabilityInfo.updateImsRcsRegistered(attr)) {
            mHandler.sendTriggeringPublishMessage(PublishController.PUBLISH_TRIGGER_RCS_REGISTERED);
        }
    }

    /*
     * This method is called when RCS is unregistered.
     */
    private void handleImsRcsUnregistered() {
        mCapabilityInfo.updateImsRcsUnregistered();
        mHandler.sendTriggeringPublishMessage(PublishController.PUBLISH_TRIGGER_RCS_UNREGISTERED);
        if (mCapabilityInfo.updateImsRcsUnregistered()) {
            mHandler.sendTriggeringPublishMessage(
                    PublishController.PUBLISH_TRIGGER_RCS_UNREGISTERED);
        }
    }

    /*
+40 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.Instant;
import java.util.Set;

/**
 * The interface related to the PUBLISH request.
@@ -71,6 +72,9 @@ public interface PublishController extends ControllerBase {
    /** Publish trigger type: provisioning changes */
    int PUBLISH_TRIGGER_PROVISIONING_CHANGE = 12;

    /**The caps have been overridden for a test*/
    int PUBLISH_TRIGGER_OVERRIDE_CAPS = 13;

    @IntDef(value = {
            PUBLISH_TRIGGER_SERVICE,
            PUBLISH_TRIGGER_RETRY,
@@ -83,7 +87,8 @@ public interface PublishController extends ControllerBase {
            PUBLISH_TRIGGER_MMTEL_CAPABILITY_CHANGE,
            PUBLISH_TRIGGER_RCS_REGISTERED,
            PUBLISH_TRIGGER_RCS_UNREGISTERED,
            PUBLISH_TRIGGER_PROVISIONING_CHANGE
            PUBLISH_TRIGGER_PROVISIONING_CHANGE,
            PUBLISH_TRIGGER_OVERRIDE_CAPS
    }, prefix="PUBLISH_TRIGGER_")
    @Retention(RetentionPolicy.SOURCE)
    @interface PublishTriggerType {}
@@ -129,11 +134,45 @@ public interface PublishController extends ControllerBase {
        void updatePublishThrottle(int value);
    }

    /**
     * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
     * <p>
     * Used for testing ONLY.
     * @return the new capabilities that will be used for PUBLISH.
     */
    RcsContactUceCapability addRegistrationOverrideCapabilities(Set<String> featureTags);

    /**
     * Remove existing feature tags to the Set used to calculate the capabilities in PUBLISH.
     * <p>
     * Used for testing ONLY.
     * @return the new capabilities that will be used for PUBLISH.
     */
    RcsContactUceCapability removeRegistrationOverrideCapabilities(Set<String> featureTags);

    /**
     * Clear all overrides in the Set used to calculate the capabilities in PUBLISH.
     * <p>
     * Used for testing ONLY.
     * @return the new capabilities that will be used for PUBLISH.
     */
    RcsContactUceCapability clearRegistrationOverrideCapabilities();

    /**
     * @return latest RcsContactUceCapability instance that will be used for PUBLISH.
     */
    RcsContactUceCapability getLatestRcsContactUceCapability();

    /**
     * Retrieve the RCS UCE Publish state.
     */
    @PublishState int getUcePublishState();

    /**
     * @return the last PIDF XML used for publish or {@code null} if the device is not published.
     */
    String getLastPidfXml();

    /**
     * Notify that the device's capabilities have been unpublished from the network.
     */
+42 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
 * The implementation of PublishController.
@@ -226,6 +227,44 @@ public class PublishControllerImpl implements PublishController {
        }
    }

    @Override
    public RcsContactUceCapability addRegistrationOverrideCapabilities(Set<String> featureTags) {
        if (mDeviceCapabilityInfo.addRegistrationOverrideCapabilities(featureTags)) {
            mPublishHandler.requestPublish(PublishController.PUBLISH_TRIGGER_OVERRIDE_CAPS);
        }
        return mDeviceCapabilityInfo.getDeviceCapabilities(
                RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE, mContext);
    }

    @Override
    public RcsContactUceCapability removeRegistrationOverrideCapabilities(Set<String> featureTags) {
        if (mDeviceCapabilityInfo.removeRegistrationOverrideCapabilities(featureTags)) {
            mPublishHandler.requestPublish(PublishController.PUBLISH_TRIGGER_OVERRIDE_CAPS);
        }
        return mDeviceCapabilityInfo.getDeviceCapabilities(
                RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE, mContext);
    }

    @Override
    public RcsContactUceCapability clearRegistrationOverrideCapabilities() {
        if (mDeviceCapabilityInfo.clearRegistrationOverrideCapabilities()) {
            mPublishHandler.requestPublish(PublishController.PUBLISH_TRIGGER_OVERRIDE_CAPS);
        }
        return mDeviceCapabilityInfo.getDeviceCapabilities(
                RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE, mContext);
    }

    @Override
    public RcsContactUceCapability getLatestRcsContactUceCapability() {
        return mDeviceCapabilityInfo.getDeviceCapabilities(
                RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE, mContext);
    }

    @Override
    public String getLastPidfXml() {
        return mPidfXml;
    }

    /**
     * Register a {@link PublishStateCallback} to listen to the published state changed.
     */
@@ -700,6 +739,9 @@ public class PublishControllerImpl implements PublishController {
            pw.println("mPublishProcessor is null");
        }

        pw.println();
        mDeviceCapListener.dump(pw);

        pw.println("Log:");
        pw.increaseIndent();
        mLocalLog.dump(pw);
Loading