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

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

When the capability type is SIP OPTIONS, the PUBLISH STATE should be OK am: 4b733da9

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

Change-Id: I48e321c57a722594b42394333245144ddd1e060d
parents 8003737a 4b733da9
Loading
Loading
Loading
Loading
+103 −11
Original line number Diff line number Diff line
@@ -89,6 +89,8 @@ public class PublishControllerImpl implements PublishController {
    private volatile RcsFeatureManager mRcsFeatureManager;
    private final UceControllerCallback mUceCtrlCallback;

    // The capability type that the device is using.
    private @RcsImsCapabilityFlag int mCapabilityType;
    // The device publish state
    private @PublishState int mPublishState;
    // The timestamp of updating the publish state
@@ -154,7 +156,8 @@ public class PublishControllerImpl implements PublishController {
    }

    private void initPublishController(Looper looper) {
        mPublishState = RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED;
        mCapabilityType = PublishUtils.getCapabilityType(mContext, mSubId);
        mPublishState = getInitialPublishState(mCapabilityType);
        mPublishStateCallbacks = new RemoteCallbackList<>();
        mPublishHandler = new PublishHandler(this, looper);

@@ -166,6 +169,26 @@ public class PublishControllerImpl implements PublishController {

        // Turn on the listener to listen to the device changes.
        mDeviceCapListener.initialize();

        logd("initPublishController completed: capabilityType=" + mCapabilityType +
                ", publishState=" + mPublishState);
    }

    /**
     * Get the initial publish state according to the given capability type.
     * <p>
     * The default publish state is NOT_PUBLISH when the capability type is PRESENCE.
     * The default publish state is OK when the capability type is SIP OPTIONS.
     * Otherwise, the default initial value is ERROR.
     */
    private int getInitialPublishState(@RcsImsCapabilityFlag int capabilityType) {
        if (capabilityType == RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE) {
            return RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED;
        } else if (capabilityType == RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE) {
            return RcsUceAdapter.PUBLISH_STATE_OK;
        } else {
            return RcsUceAdapter.PUBLISH_STATE_OTHER_ERROR;
        }
    }

    private void initPublishProcessor() {
@@ -573,14 +596,7 @@ public class PublishControllerImpl implements PublishController {
        }

        public void sendPublishMessage(@PublishTriggerType int type) {
            PublishControllerImpl publishCtrl = mPublishControllerRef.get();
            if (publishCtrl == null) return;
            if (publishCtrl.mIsDestroyedFlag) return;

            Message message = obtainMessage();
            message.what = MSG_REQUEST_PUBLISH;
            message.arg1 = type;
            sendMessage(message);
            sendPublishMessage(type, 0L);
        }

        public void sendPublishMessage(@PublishTriggerType int type, long delay) {
@@ -588,6 +604,13 @@ public class PublishControllerImpl implements PublishController {
            if (publishCtrl == null) return;
            if (publishCtrl.mIsDestroyedFlag) return;

            // Disallow publish if the PRESENCE PUBLISH is not enabled and this request is not
            // triggered by the ImsService.
            if (!publishCtrl.isPresencePublishEnabled() && type != PUBLISH_TRIGGER_SERVICE) {
                publishCtrl.logd("sendPublishMessage: disallowed type=" + type);
                return;
            }

            Message message = obtainMessage();
            message.what = MSG_REQUEST_PUBLISH;
            message.arg1 = type;
@@ -692,7 +715,8 @@ public class PublishControllerImpl implements PublishController {

        // The first PUBLISH request is required to be triggered from the service.
        if (!mReceivePublishFromService) {
            logd("isPublishRequestAllowed: Have not received the first PUBLISH from the service.");
            logd("isPublishRequestAllowed: "
                    + "The first PUBLISH request from the server has not been received.");
            return false;
        }

@@ -713,6 +737,19 @@ public class PublishControllerImpl implements PublishController {
        return true;
    }

    /**
     * Check whether the PRESENCE PUBLISH should be enabled or not. It should be enabled only when
     * the PRESENCE mechanism is supported.
     */
    private boolean isPresencePublishEnabled() {
        synchronized (mPublishStateLock) {
            return mCapabilityType == RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE;
        }
    }

    /**
     * Handle the RCS connected message. This method is called in the handler thread.
     */
    private void handleRcsConnectedMessage(RcsFeatureManager manager) {
        if (mIsDestroyedFlag) return;
        mRcsFeatureManager = manager;
@@ -721,15 +758,27 @@ public class PublishControllerImpl implements PublishController {
        registerRcsAvailabilityChanged(manager);
    }

    /**
     * Handle the RCS disconnected message. This method is called in the handler thread.
     */
    private void handleRcsDisconnectedMessage() {
        if (mIsDestroyedFlag) return;
        mRcsFeatureManager = null;
        onUnpublish();
        mDeviceCapabilityInfo.updatePresenceCapable(false);
        mDeviceCapListener.onRcsDisconnected();
        mPublishProcessor.onRcsDisconnected();

        // When the RCS is disconnected, update the publish state to NOT_PUBLISH if the PRESENCE
        // PUBLISH is enabled.
        if (isPresencePublishEnabled()) {
            handlePublishStateChangedMessage(RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED,
                    Instant.now(), null /*pidfXml*/);
        }
    }

    /**
     * Handle the Destroyed message. This method is called in the handler thread.
     */
    private void handleDestroyedMessage() {
        mIsDestroyedFlag = true;
        mDeviceCapabilityInfo.updatePresenceCapable(false);
@@ -768,8 +817,14 @@ public class PublishControllerImpl implements PublishController {
        }
    }

    /**
     * Handle the carrier config changed message. This method is called in the handler thread.
     */
    private void handleCarrierConfigChangedMessage() {
        if (mIsDestroyedFlag) return;

        updateCapabilityTypeAndPublishStateIfNeeded();

        String[] newMap = getCarrierServiceDescriptionFeatureTagMap();
        if (mDeviceCapabilityInfo.updateCapabilityRegistrationTrackerMap(newMap)) {
            mPublishHandler.sendPublishMessage(
@@ -777,6 +832,37 @@ public class PublishControllerImpl implements PublishController {
        }
    }

    /**
     * Check whether the capability type has changed or not because of the carrier config changed.
     * If the capability type has changed, the publish state also needs to be reinitialized.
     * <p>
     * This method is called in the handler thread.
     */
    private void updateCapabilityTypeAndPublishStateIfNeeded() {
        synchronized (mPublishStateLock) {
            int originalMechanism = mCapabilityType;
            mCapabilityType = PublishUtils.getCapabilityType(mContext, mSubId);

            // Return when the capability type has not changed.
            if (originalMechanism == mCapabilityType) {
                logd("updateCapTypeAndPublishStateIfNeeded: " +
                        "The capability type is not changed=" + mCapabilityType);
                return;
            }

            // Reinitialize the publish state because the capability type has changed.
            int updatedPublishState = getInitialPublishState(mCapabilityType);

            logd("updateCapTypeAndPublishStateIfNeeded from " + originalMechanism +
                    " to " + mCapabilityType + ", new publish state=" + updatedPublishState);

            // Update the publish state directly. Because this method is called in the
            // handler thread already, the process of updating publish state does not need to be
            // sent to the looper again.
            handlePublishStateChangedMessage(updatedPublishState, Instant.now(), null /*pidfxml*/);
        }
    }

    private String[] getCarrierServiceDescriptionFeatureTagMap() {
        CarrierConfigManager manager = mContext.getSystemService(CarrierConfigManager.class);
        PersistableBundle bundle = manager != null ? manager.getConfigForSubId(mSubId) :
@@ -898,6 +984,12 @@ public class PublishControllerImpl implements PublishController {
        mUceCtrlCallback.resetDeviceState();
    }

    @VisibleForTesting
    public void setCapabilityType(int type) {
        mCapabilityType = type;
        mPublishState = getInitialPublishState(mCapabilityType);
    }

    @VisibleForTesting
    public void setPublishStateCallback(RemoteCallbackList<IRcsUcePublishStateCallback> list) {
        mPublishStateCallbacks = list;
+15 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import android.content.Context;
import android.net.Uri;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag;
import android.text.TextUtils;
import android.util.Log;

@@ -133,4 +135,17 @@ public class PublishUtils {
            return telephonyManager.createForSubscriptionId(subId);
        }
    }

    static @RcsImsCapabilityFlag int getCapabilityType(Context context, int subId) {
        boolean isPresenceSupported = UceUtils.isPresenceSupported(context, subId);
        boolean isSipOptionsSupported = UceUtils.isSipOptionsSupported(context, subId);
        if (isPresenceSupported) {
            return RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE;
        } else if (isSipOptionsSupported) {
            return RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE;
        } else {
            // Return NONE when neither OPTIONS nor PRESENCE is supported.
            return RcsImsCapabilities.CAPABILITY_TYPE_NONE;
        }
    }
}
+32 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.os.RemoteCallbackList;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -315,11 +316,42 @@ public class PublishControllerImplTest extends ImsTestBase {
        assertFalse("still contained 555-555-1212: " + testString, result.contains("555-555-1212"));
    }

    @Test
    @SmallTest
    public void testNotPublishWhitSipOptions() throws Exception {
        PublishControllerImpl publishController = createPublishController();
        publishController.setCapabilityType(RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE);
        doReturn(Optional.of(0L)).when(mPublishProcessor).getPublishingDelayTime();

        // Trigger a publish request (VT changes)
        PublishControllerCallback callback = publishController.getPublishControllerCallback();
        callback.requestPublishFromInternal(PUBLISH_TRIGGER_VT_SETTING_CHANGE);
        Handler handler = publishController.getPublishHandler();
        waitForHandlerAction(handler, 1000);

        // Verify it cannot be processed because the capability type is SIP OPTIONS and the publish
        // request is triggered from device changed
        verify(mPublishProcessor, never()).doPublish(PUBLISH_TRIGGER_VT_SETTING_CHANGE);

        // Set the PRESENCE is capable
        IImsCapabilityCallback RcsCapCallback = publishController.getRcsCapabilitiesCallback();
        RcsCapCallback.onCapabilitiesStatusChanged(RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE);

        // Trigger the PUBLISH request from the service.
        publishController.requestPublishCapabilitiesFromService(
                RcsUceAdapter.CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN);
        waitForHandlerAction(handler, 1000);

        // Verify the request which is from the service can be processed
        verify(mPublishProcessor).doPublish(PublishController.PUBLISH_TRIGGER_SERVICE);
    }

    private PublishControllerImpl createPublishController() {
        PublishControllerImpl publishController = new PublishControllerImpl(mContext, mSubId,
                mUceCtrlCallback, Looper.getMainLooper(), mDeviceCapListenerFactory,
                mPublishProcessorFactory);
        publishController.setPublishStateCallback(mPublishStateCallbacks);
        publishController.setCapabilityType(RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE);
        return publishController;
    }
}