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

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

Fix CTS failed when trigger the remote capability request to the UCE framework...

Fix CTS failed when trigger the remote capability request to the UCE framework am: 289f0842 am: bd26d03c

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

Change-Id: I6afca57e6b8b7e5d04c6b6fad6b020d3defbccc6
parents 8b40a5b3 bd26d03c
Loading
Loading
Loading
Loading
+155 −10
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.ims.rcs.uce;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -48,12 +49,16 @@ import com.android.ims.rcs.uce.request.UceRequestManager;
import com.android.ims.rcs.uce.util.UceUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.os.SomeArgs;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
@@ -183,12 +188,94 @@ public class UceController {
        }
    };

    /**
     * Cache the capabilities events triggered by the ImsService during the RCS connected procedure.
     */
    private static class CachedCapabilityEvent {
        private Optional<Integer> mRequestPublishCapabilitiesEvent;
        private Optional<Boolean> mUnpublishEvent;
        private Optional<SomeArgs> mRemoteCapabilityRequestEvent;

        public CachedCapabilityEvent() {
            mRequestPublishCapabilitiesEvent = Optional.empty();
            mUnpublishEvent = Optional.empty();
            mRemoteCapabilityRequestEvent = Optional.empty();
        }

        /**
         * Cache the publish capabilities request event triggered by the ImsService.
         */
        public synchronized void setRequestPublishCapabilitiesEvent(int triggerType) {
            mRequestPublishCapabilitiesEvent = Optional.of(triggerType);
        }

        /**
         * Cache the unpublish event triggered by the ImsService.
         */
        public synchronized void setOnUnpublishEvent() {
            mUnpublishEvent = Optional.of(Boolean.TRUE);
        }

        /**
         * Cache the remote capability request event triggered by the ImsService.
         */
        public synchronized void setRemoteCapabilityRequestEvent(Uri contactUri,
                List<String> remoteCapabilities, IOptionsRequestCallback callback) {
            SomeArgs args = SomeArgs.obtain();
            args.arg1 = contactUri;
            args.arg2 = remoteCapabilities;
            args.arg3 = callback;
            mRemoteCapabilityRequestEvent = Optional.of(args);
        }

        /** @Return the cached publish request event */
        public synchronized Optional<Integer> getRequestPublishEvent() {
            return mRequestPublishCapabilitiesEvent;
        }

        /** @Return the cached unpublish event */
        public synchronized Optional<Boolean> getUnpublishEvent() {
            return mUnpublishEvent;
        }

        /** @Return the cached remote capability request event */
        public synchronized Optional<SomeArgs> getRemoteCapabilityRequestEvent() {
            return mRemoteCapabilityRequestEvent;
        }

        /** Clear the cached */
        public synchronized void clear() {
            mRequestPublishCapabilitiesEvent = Optional.empty();
            mUnpublishEvent = Optional.empty();
            mRemoteCapabilityRequestEvent.ifPresent(args -> args.recycle());
            mRemoteCapabilityRequestEvent = Optional.empty();
        }
    }

    /** The RCS state is disconnected */
    private static final int RCS_STATE_DISCONNECTED = 0;

    /** The RCS state is connecting */
    private static final int RCS_STATE_CONNECTING = 1;

    /** The RCS state is connected */
    private static final int RCS_STATE_CONNECTED = 2;

    @IntDef(value = {
        RCS_STATE_DISCONNECTED,
        RCS_STATE_CONNECTING,
        RCS_STATE_CONNECTED,
    }, prefix="RCS_STATE_")
    @Retention(RetentionPolicy.SOURCE)
    @interface RcsConnectedState {}

    private final int mSubId;
    private final Context mContext;
    private final LocalLog mLocalLog = new LocalLog(UceUtils.LOG_SIZE);
    private volatile boolean mIsRcsConnected;

    private volatile Looper mLooper;
    private volatile boolean mIsDestroyedFlag;
    private Looper mLooper;
    private volatile @RcsConnectedState int mRcsConnectedState;

    private RcsFeatureManager mRcsFeatureManager;
    private EabController mEabController;
@@ -200,10 +287,15 @@ public class UceController {
    // The server state for UCE requests.
    private final ServerState mServerState;

    // The cache of the capability request event triggered by ImsService
    private final CachedCapabilityEvent mCachedCapabilityEvent;

    public UceController(Context context, int subId) {
        mSubId = subId;
        mContext = context;
        mServerState = new ServerState();
        mCachedCapabilityEvent = new CachedCapabilityEvent();
        mRcsConnectedState = RCS_STATE_DISCONNECTED;
        logi("create");

        initLooper();
@@ -219,6 +311,8 @@ public class UceController {
        mServerState = serverState;
        mControllerFactory = controllerFactory;
        mRequestManagerFactory = requestManagerFactory;
        mCachedCapabilityEvent = new CachedCapabilityEvent();
        mRcsConnectedState = RCS_STATE_DISCONNECTED;
        initLooper();
        initControllers();
        initRequestManager();
@@ -252,15 +346,23 @@ public class UceController {
     */
    public void onRcsConnected(RcsFeatureManager manager) {
        logi("onRcsConnected");
        mIsRcsConnected = true;
        // Set the RCS is connecting flag
        mRcsConnectedState = RCS_STATE_CONNECTING;

        // Listen to the capability exchange event which is triggered by the ImsService
        mRcsFeatureManager = manager;
        mRcsFeatureManager.addCapabilityEventCallback(mCapabilityEventListener);

        // Notify each controllers that RCS is connected.
        mEabController.onRcsConnected(manager);
        mPublishController.onRcsConnected(manager);
        mSubscribeController.onRcsConnected(manager);
        mOptionsController.onRcsConnected(manager);
        // Listen to the capability exchange event which is triggered by the ImsService
        mRcsFeatureManager = manager;
        mRcsFeatureManager.addCapabilityEventCallback(mCapabilityEventListener);

        // Set the RCS is connected flag and check if there is any capability event received during
        // the connecting process.
        mRcsConnectedState = RCS_STATE_CONNECTED;
        handleCachedCapabilityEvent();
    }

    /**
@@ -268,7 +370,7 @@ public class UceController {
     */
    public void onRcsDisconnected() {
        logi("onRcsDisconnected");
        mIsRcsConnected = false;
        mRcsConnectedState = RCS_STATE_DISCONNECTED;
        // Remove the listener because RCS is disconnected.
        if (mRcsFeatureManager != null) {
            mRcsFeatureManager.removeCapabilityEventCallback(mCapabilityEventListener);
@@ -313,6 +415,24 @@ public class UceController {
        mOptionsController.onCarrierConfigChanged();
    }

    private void handleCachedCapabilityEvent() {
        Optional<Integer> requestPublishEvent = mCachedCapabilityEvent.getRequestPublishEvent();
        requestPublishEvent.ifPresent(triggerType ->
            onRequestPublishCapabilitiesFromService(triggerType));

        Optional<Boolean> unpublishEvent = mCachedCapabilityEvent.getUnpublishEvent();
        unpublishEvent.ifPresent(unpublish -> onUnpublish());

        Optional<SomeArgs> remoteRequest = mCachedCapabilityEvent.getRemoteCapabilityRequestEvent();
        remoteRequest.ifPresent(args -> {
            Uri contactUri = (Uri) args.arg1;
            List<String> remoteCapabilities = (List<String>) args.arg2;
            IOptionsRequestCallback callback = (IOptionsRequestCallback) args.arg3;
            retrieveOptionsCapabilitiesForRemote(contactUri, remoteCapabilities, callback);
        });
        mCachedCapabilityEvent.clear();
    }

    /*
     * The implementation of the interface UceControllerCallback. These methods are called by other
     * controllers.
@@ -374,18 +494,35 @@ public class UceController {
            new RcsFeatureManager.CapabilityExchangeEventCallback() {
                @Override
                public void onRequestPublishCapabilities(
                        @StackPublishTriggerType int publishTriggerType) {
                    onRequestPublishCapabilitiesFromService(publishTriggerType);
                        @StackPublishTriggerType int triggerType) {
                    if (isRcsConnecting()) {
                        mCachedCapabilityEvent.setRequestPublishCapabilitiesEvent(triggerType);
                        return;
                    }
                    onRequestPublishCapabilitiesFromService(triggerType);
                }

                @Override
                public void onUnpublish() {
                    if (isRcsConnecting()) {
                        mCachedCapabilityEvent.setOnUnpublishEvent();
                        return;
                    }
                    UceController.this.onUnpublish();
                }

                @Override
                public void onRemoteCapabilityRequest(Uri contactUri,
                        List<String> remoteCapabilities, IOptionsRequestCallback cb) {
                    if (contactUri == null || remoteCapabilities == null || cb == null) {
                        logw("onRemoteCapabilityRequest: parameter cannot be null");
                        return;
                    }
                    if (isRcsConnecting()) {
                        mCachedCapabilityEvent.setRemoteCapabilityRequestEvent(contactUri,
                                remoteCapabilities, cb);
                        return;
                    }
                    retrieveOptionsCapabilitiesForRemote(contactUri, remoteCapabilities, cb);
                }
            };
@@ -577,12 +714,20 @@ public class UceController {
     * @return true if RCS is connected without destroyed.
     */
    public boolean isUnavailable() {
        if (!mIsRcsConnected || mIsDestroyedFlag) {
        if (!isRcsConnected() || mIsDestroyedFlag) {
            return true;
        }
        return false;
    }

    private boolean isRcsConnecting() {
        return mRcsConnectedState == RCS_STATE_CONNECTING;
    }

    private boolean isRcsConnected() {
        return mRcsConnectedState == RCS_STATE_CONNECTED;
    }

    /**
     * The internal class to store the server state which sent from the network. It will help to
     * check if the network allows the UCE request.