IMS RCS API Improvements-SipDelegate

Bug: b/197892699, b/205194548
Test: atest DelegateStateTrackerTest
Change-Id: I3c5a7834688e6aa1294f9be7d8a37984c43ed26a
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index 7d594d1..3618d58 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -582,6 +582,7 @@
             throw new SecurityException("Passed in PackageName can not be found on device");
         }
 
+        final int uid = Binder.getCallingUid();
         final long identity = Binder.clearCallingIdentity();
         SipTransportController transport = getRcsFeatureController(subId).getFeature(
                 SipTransportController.class);
@@ -590,7 +591,7 @@
                     "This subscription does not support the creation of SIP delegates");
         }
         try {
-            transport.createSipDelegate(subId, request, packageName, delegateState,
+            transport.createSipDelegate(subId, uid, request, packageName, delegateState,
                     delegateMessage);
         } catch (ImsException e) {
             throw new ServiceSpecificException(e.getCode(), e.getMessage());
diff --git a/src/com/android/services/telephony/rcs/DelegateStateTracker.java b/src/com/android/services/telephony/rcs/DelegateStateTracker.java
index 18aab88..64090d5 100644
--- a/src/com/android/services/telephony/rcs/DelegateStateTracker.java
+++ b/src/com/android/services/telephony/rcs/DelegateStateTracker.java
@@ -16,6 +16,10 @@
 
 package com.android.services.telephony.rcs;
 
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
+import android.os.Build;
 import android.os.RemoteException;
 import android.telephony.ims.DelegateRegistrationState;
 import android.telephony.ims.FeatureTagState;
@@ -28,6 +32,7 @@
 import android.util.LocalLog;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.metrics.RcsStats;
 
 import java.io.PrintWriter;
@@ -43,25 +48,58 @@
     private static final String LOG_TAG = "DelegateST";
 
     private final int mSubId;
+    private final int mUid;
     private final ISipDelegateConnectionStateCallback mAppStateCallback;
     private final ISipDelegate mLocalDelegateImpl;
 
     private final LocalLog mLocalLog = new LocalLog(SipTransportController.LOG_SIZE);
 
+    private final RcsStats mRcsStats;
+
     private List<FeatureTagState> mDelegateDeniedTags;
     private DelegateRegistrationState mLastRegState;
     private boolean mCreatedCalled = false;
     private int mRegistrationStateOverride = -1;
-
+    private CompatChangesFactory mCompatChangesFactory;
     private Set<String> mDelegateSupportedTags;
-    private final RcsStats mRcsStats;
 
-    public DelegateStateTracker(int subId, ISipDelegateConnectionStateCallback appStateCallback,
+    /**
+     * Interface for checking compatibility of apps
+     */
+    public interface CompatChangesFactory {
+        /**
+         *  @param changeId The ID of the compatibility change.
+         *  @param uid      The UID of the app.
+         *  @return {@code true} if the change is enabled for the current app.
+         */
+        boolean isChangeEnabled(long changeId, int uid);
+    }
+
+    /**
+     * For apps targeting Android T and above, support the REGISTERING state on APIs, such as
+     * {@code DelegateRegistrationState#addRegisteringFeatureTags} and
+     * {@code DelegateRegistrationState#getRegisteringFeatureTags}
+     * @hide
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
+    @VisibleForTesting
+    public static final long SUPPORT_REGISTERING_DELEGATE_STATE = 205194548;
+
+    public DelegateStateTracker(int subId, int uid,
+            ISipDelegateConnectionStateCallback appStateCallback,
             ISipDelegate localDelegateImpl, RcsStats rcsStats) {
         mSubId = subId;
+        mUid = uid;
         mAppStateCallback = appStateCallback;
         mLocalDelegateImpl = localDelegateImpl;
         mRcsStats = rcsStats;
+        setCompatChangesFactory((changeId, uid1) -> CompatChanges.isChangeEnabled(changeId, uid1));
+    }
+
+    @VisibleForTesting
+    protected void setCompatChangesFactory(CompatChangesFactory factory) {
+        mCompatChangesFactory = factory;
     }
 
     /**
@@ -140,6 +178,9 @@
      */
     @Override
     public void onRegistrationStateChanged(DelegateRegistrationState registrationState) {
+        if (!mCompatChangesFactory.isChangeEnabled(SUPPORT_REGISTERING_DELEGATE_STATE, mUid)) {
+            registrationState = overrideRegistrationForCompatibility(registrationState);
+        }
         if (mRegistrationStateOverride > DelegateRegistrationState.DEREGISTERED_REASON_UNKNOWN) {
             logi("onRegistrationStateChanged: overriding registered state to "
                     + mRegistrationStateOverride);
@@ -204,6 +245,7 @@
     private DelegateRegistrationState overrideRegistrationForDelegateChange(
             int registerOverrideReason, DelegateRegistrationState state) {
         Set<String> registeredFeatures = state.getRegisteredFeatureTags();
+        Set<String> registeringFeatures = state.getRegisteringFeatureTags();
         DelegateRegistrationState.Builder overriddenState = new DelegateRegistrationState.Builder();
         // keep other deregistering/deregistered tags the same.
         for (FeatureTagState dereging : state.getDeregisteringFeatureTags()) {
@@ -214,13 +256,41 @@
             overriddenState.addDeregisteredFeatureTag(dereged.getFeatureTag(),
                     dereged.getState());
         }
-        // Override REGISTERED only
+        // Override REGISTERING/REGISTERED
+        for (String ft : registeringFeatures) {
+            overriddenState.addDeregisteringFeatureTag(ft, registerOverrideReason);
+        }
         for (String ft : registeredFeatures) {
             overriddenState.addDeregisteringFeatureTag(ft, registerOverrideReason);
         }
         return overriddenState.build();
     }
 
+    private DelegateRegistrationState overrideRegistrationForCompatibility(
+            DelegateRegistrationState state) {
+        Set<String> registeredFeatures = state.getRegisteredFeatureTags();
+        Set<String> registeringFeatures = state.getRegisteringFeatureTags();
+        DelegateRegistrationState.Builder overriddenState = new DelegateRegistrationState.Builder();
+        // keep other registered/deregistering/deregistered tags the same.
+        for (FeatureTagState dereging : state.getDeregisteringFeatureTags()) {
+            overriddenState.addDeregisteringFeatureTag(dereging.getFeatureTag(),
+                    dereging.getState());
+        }
+        for (FeatureTagState dereged : state.getDeregisteredFeatureTags()) {
+            overriddenState.addDeregisteredFeatureTag(dereged.getFeatureTag(),
+                    dereged.getState());
+        }
+        overriddenState.addRegisteredFeatureTags(registeredFeatures);
+
+        // move the REGISTERING state to the DEREGISTERED state.
+        for (String tag : registeringFeatures) {
+            overriddenState.addDeregisteredFeatureTag(tag,
+                    DelegateRegistrationState.DEREGISTERED_REASON_NOT_REGISTERED);
+        }
+
+        return overriddenState.build();
+    }
+
     private void notifySipDelegateCreated() {
         try {
             mAppStateCallback.onCreated(mLocalDelegateImpl);
diff --git a/src/com/android/services/telephony/rcs/SipDelegateController.java b/src/com/android/services/telephony/rcs/SipDelegateController.java
index c728141..860a6d9 100644
--- a/src/com/android/services/telephony/rcs/SipDelegateController.java
+++ b/src/com/android/services/telephony/rcs/SipDelegateController.java
@@ -78,6 +78,7 @@
     }
 
     private final int mSubId;
+    private final int mUid;
     private final String mPackageName;
     private final DelegateRequest mInitialRequest;
     private final ScheduledExecutorService mExecutorService;
@@ -89,12 +90,13 @@
     private DelegateBinderStateManager mBinderConnection;
     private Set<String> mTrackedFeatureTags;
 
-    public SipDelegateController(int subId, DelegateRequest initialRequest, String packageName,
-            ISipTransport transportImpl, IImsRegistration registrationImpl,
+    public SipDelegateController(int subId, int uid, DelegateRequest initialRequest,
+            String packageName, ISipTransport transportImpl, IImsRegistration registrationImpl,
             ScheduledExecutorService executorService,
             ISipDelegateConnectionStateCallback stateCallback,
             ISipDelegateMessageCallback messageCallback) {
         mSubId = subId;
+        mUid = uid;
         mPackageName = packageName;
         mInitialRequest = initialRequest;
         mExecutorService = executorService;
@@ -102,7 +104,8 @@
 
         mMessageTransportWrapper = new MessageTransportWrapper(mSubId, executorService,
                 messageCallback);
-        mDelegateStateTracker = new DelegateStateTracker(mSubId, stateCallback,
+
+        mDelegateStateTracker = new DelegateStateTracker(mSubId, mUid, stateCallback,
                 mMessageTransportWrapper.getDelegateConnection(), RcsStats.getInstance());
     }
 
@@ -110,12 +113,13 @@
      * Inject dependencies for testing only.
      */
     @VisibleForTesting
-    public SipDelegateController(int subId, DelegateRequest initialRequest, String packageName,
-            ScheduledExecutorService executorService,
+    public SipDelegateController(int subId, int uid, DelegateRequest initialRequest,
+            String packageName, ScheduledExecutorService executorService,
             MessageTransportWrapper messageTransportWrapper,
             DelegateStateTracker delegateStateTracker,
             DelegateBinderStateManager.Factory connectionFactory) {
         mSubId = subId;
+        mUid = uid;
         mInitialRequest = initialRequest;
         mPackageName = packageName;
         mExecutorService = executorService;
diff --git a/src/com/android/services/telephony/rcs/SipTransportController.java b/src/com/android/services/telephony/rcs/SipTransportController.java
index 709e142..0aa3aa0 100644
--- a/src/com/android/services/telephony/rcs/SipTransportController.java
+++ b/src/com/android/services/telephony/rcs/SipTransportController.java
@@ -243,9 +243,9 @@
     @VisibleForTesting
     public interface SipDelegateControllerFactory {
         /** See {@link SipDelegateController} */
-        SipDelegateController create(int subId, DelegateRequest initialRequest, String packageName,
-                ISipTransport sipTransportImpl,  IImsRegistration registrationImpl,
-                ScheduledExecutorService executorService,
+        SipDelegateController create(int subId, int uid, DelegateRequest initialRequest,
+                String packageName, ISipTransport sipTransportImpl,
+                IImsRegistration registrationImpl, ScheduledExecutorService executorService,
                 ISipDelegateConnectionStateCallback stateCallback,
                 ISipDelegateMessageCallback messageCallback);
     }
@@ -364,17 +364,18 @@
      * {@link ISipDelegateConnectionStateCallback#onCreated(ISipDelegate)} must be called with
      * the AIDL instance corresponding to the remote {@link SipDelegate}.
      * @param subId the subId associated with the request.
+     * @param uid the uid associated with the request
      * @param request The request parameters used to create the {@link SipDelegate}.
      * @param delegateState The {@link DelegateConnectionStateCallback} Binder connection.
      * @param delegateMessage The {@link DelegateConnectionMessageCallback} Binder Connection
      * @throws ImsException if the request to create the {@link SipDelegate} did not complete.
      */
-    public void createSipDelegate(int subId, DelegateRequest request, String packageName,
+    public void createSipDelegate(int subId, int uid, DelegateRequest request, String packageName,
             ISipDelegateConnectionStateCallback delegateState,
             ISipDelegateMessageCallback delegateMessage) throws ImsException {
         logi("createSipDelegate: request= " + request + ", packageName= " + packageName);
         CompletableFuture<ImsException> result = new CompletableFuture<>();
-        mExecutorService.submit(() -> createSipDelegateInternal(subId, request, packageName,
+        mExecutorService.submit(() -> createSipDelegateInternal(subId, uid, request, packageName,
                 delegateState,
                 // Capture any ImsExceptions generated during the process.
                 delegateMessage, result::complete));
@@ -423,8 +424,8 @@
         return result;
     }
 
-    private void createSipDelegateInternal(int subId, DelegateRequest request, String packageName,
-            ISipDelegateConnectionStateCallback delegateState,
+    private void createSipDelegateInternal(int subId, int uid, DelegateRequest request,
+            String packageName, ISipDelegateConnectionStateCallback delegateState,
             ISipDelegateMessageCallback delegateMessage,
             Consumer<ImsException> startedErrorConsumer) {
         ISipTransport transport;
@@ -450,8 +451,9 @@
             return;
         }
 
-        SipDelegateController c = mDelegateControllerFactory.create(subId, request, packageName,
-                transport, registration, mExecutorService, delegateState, delegateMessage);
+        SipDelegateController c = mDelegateControllerFactory.create(subId, uid, request,
+                packageName, transport, registration, mExecutorService, delegateState,
+                delegateMessage);
         logi("createSipDelegateInternal: request= " + request + ", packageName= " + packageName
                 + ", controller created: " + c);
         addPendingCreateAndEvaluate(c);
diff --git a/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java b/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java
index 25b5339..0eb19e7 100644
--- a/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.services.telephony.rcs;
 
+import static com.android.services.telephony.rcs.DelegateStateTracker.SUPPORT_REGISTERING_DELEGATE_STATE;
+
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -24,7 +26,9 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.app.compat.CompatChanges;
 import android.net.InetAddresses;
+import android.os.Binder;
 import android.telephony.ims.DelegateRegistrationState;
 import android.telephony.ims.FeatureTagState;
 import android.telephony.ims.SipDelegateConfiguration;
@@ -33,8 +37,8 @@
 import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
 import android.util.ArraySet;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.TelephonyTestBase;
 import com.android.internal.telephony.metrics.RcsStats;
@@ -77,8 +81,8 @@
     @SmallTest
     @Test
     public void testDelegateCreated() throws Exception {
-        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
-                mSipDelegate, mRcsStats);
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID,
+                Binder.getCallingUid(), mAppCallback, mSipDelegate, mRcsStats);
         Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
         Set<String> supportedTags = getSupportedTags();
         stateTracker.sipDelegateConnected(supportedTags, deniedTags);
@@ -114,8 +118,8 @@
     @SmallTest
     @Test
     public void testDelegateDestroyed() throws Exception {
-        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
-                mSipDelegate, mRcsStats);
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID,
+                Binder.getCallingUid(), mAppCallback, mSipDelegate, mRcsStats);
         Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
         Set<String> supportedTags = getSupportedTags();
         stateTracker.sipDelegateConnected(supportedTags, deniedTags);
@@ -139,39 +143,75 @@
     @SmallTest
     @Test
     public void testDelegateChangingRegisteredTagsOverride() throws Exception {
-        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
-                mSipDelegate, mRcsStats);
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID,
+                Binder.getCallingUid(), mAppCallback, mSipDelegate, mRcsStats);
         Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
         Set<String> supportedTags = getSupportedTags();
+        Set<String> registeringTags = getRegisteringTag();
         stateTracker.sipDelegateConnected(supportedTags, deniedTags);
+
         // SipDelegate created
         verify(mAppCallback).onCreated(mSipDelegate);
+
         DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
                 .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+                .addRegisteringFeatureTags(registeringTags)
                 .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG,
                         DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE)
                 .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
                         DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
                 .build();
+
         stateTracker.onRegistrationStateChanged(regState);
         // Simulate underlying SipDelegate switch
         stateTracker.sipDelegateChanging(
                 DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING);
         // onFeatureTagStatusChanged should now be called with registered features overridden with
         // DEREGISTERING_REASON_FEATURE_TAGS_CHANGING
-        DelegateRegistrationState overrideRegState = new DelegateRegistrationState.Builder()
+        DelegateRegistrationState.Builder overrideBuilder =
+                new DelegateRegistrationState.Builder()
                 .addDeregisteringFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG,
                         DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING)
                 // Already Deregistering/Deregistered tags should not be overridden.
                 .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG,
                         DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE)
                 .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
-                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
-                .build();
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED);
+        if (CompatChanges.isChangeEnabled(SUPPORT_REGISTERING_DELEGATE_STATE,
+                Binder.getCallingUid())) {
+            for (String tag : registeringTags) {
+                overrideBuilder.addDeregisteringFeatureTag(tag,
+                        DelegateRegistrationState.DEREGISTERING_REASON_FEATURE_TAGS_CHANGING);
+            }
+        } else {
+            for (String tag : registeringTags) {
+                overrideBuilder.addDeregisteredFeatureTag(tag,
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_REGISTERED);
+            }
+        }
+
+        DelegateRegistrationState overrideRegState = overrideBuilder.build();
+
         // new underlying SipDelegate created
         stateTracker.sipDelegateConnected(supportedTags, deniedTags);
         stateTracker.onRegistrationStateChanged(regState);
 
+        DelegateRegistrationState.Builder builder = new DelegateRegistrationState.Builder()
+                .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+                .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG,
+                        DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE)
+                .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED);
+        if (CompatChanges.isChangeEnabled(SUPPORT_REGISTERING_DELEGATE_STATE,
+                Binder.getCallingUid())) {
+            builder.addRegisteringFeatureTags(registeringTags);
+        } else {
+            for (String tag : registeringTags) {
+                builder.addDeregisteredFeatureTag(tag,
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_REGISTERED);
+            }
+        }
+        DelegateRegistrationState regStateResult = builder.build();
         // Verify registration state through the process:
         ArgumentCaptor<DelegateRegistrationState> regCaptor =
                 ArgumentCaptor.forClass(DelegateRegistrationState.class);
@@ -179,11 +219,11 @@
                 regCaptor.capture(), eq(new ArrayList<>(deniedTags)));
         List<DelegateRegistrationState> testStates = regCaptor.getAllValues();
         // feature tags should first be registered
-        assertEquals(regState, testStates.get(0));
+        assertEquals(regStateResult, testStates.get(0));
         // registered feature tags should have moved to deregistering
         assertEquals(overrideRegState, testStates.get(1));
         // and then moved back to registered after underlying FT change done.
-        assertEquals(regState, testStates.get(2));
+        assertEquals(regStateResult, testStates.get(2));
 
         //onCreate should only have been called once and onDestroy should have never been called.
         verify(mAppCallback).onCreated(mSipDelegate);
@@ -191,14 +231,102 @@
     }
 
     /**
+     * When registration states are changed in a case that an application doesn't support the new
+     * 'registering' state the 'registering' state will be moved to the 'registered' state
+     * as the old behavior.
+     */
+    @Test
+    public void testDelegateChangingRegisteredTagsRegisteringDisable() throws Exception {
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID,
+                Binder.getCallingUid(), mAppCallback, mSipDelegate, mRcsStats);
+        stateTracker.setCompatChangesFactory((changeId, uid) -> false);
+        Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        Set<String> supportedTags = getSupportedTags();
+        Set<String> registeringTags = getRegisteringTag();
+        stateTracker.sipDelegateConnected(supportedTags, deniedTags);
+        // SipDelegate created
+        verify(mAppCallback).onCreated(mSipDelegate);
+        DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+                .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+                .addRegisteringFeatureTags(registeringTags)
+                .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG,
+                        DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE)
+                .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
+                .build();
+        stateTracker.onRegistrationStateChanged(regState);
+
+        DelegateRegistrationState.Builder builder = new DelegateRegistrationState.Builder()
+                .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+                .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG,
+                        DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE)
+                .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED);
+        for (String tag : registeringTags) {
+            builder.addDeregisteredFeatureTag(tag,
+                    DelegateRegistrationState.DEREGISTERED_REASON_NOT_REGISTERED);
+        }
+        DelegateRegistrationState overrideRegState = builder.build();
+
+
+        // Verify registration state through the process:
+        ArgumentCaptor<DelegateRegistrationState> regCaptor =
+                ArgumentCaptor.forClass(DelegateRegistrationState.class);
+        verify(mAppCallback, times(1)).onFeatureTagStatusChanged(
+                regCaptor.capture(), eq(new ArrayList<>(deniedTags)));
+        List<DelegateRegistrationState> testStates = regCaptor.getAllValues();
+
+        assertEquals(overrideRegState, testStates.get(0));
+        verify(mAppCallback).onCreated(mSipDelegate);
+    }
+
+    /**
+     * When registration states are changed in a case that an application supports the new
+     * 'registering' state the state will be kept.
+     */
+    @Test
+    public void testDelegateChangingRegisteredTagsRegisteringEnable() throws Exception {
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID,
+                Binder.getCallingUid(), mAppCallback, mSipDelegate, mRcsStats);
+        stateTracker.setCompatChangesFactory((changeId, uid) -> true);
+        Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
+        Set<String> supportedTags = getSupportedTags();
+        Set<String> registeringTags = getRegisteringTag();
+        stateTracker.sipDelegateConnected(supportedTags, deniedTags);
+        // SipDelegate created
+        verify(mAppCallback).onCreated(mSipDelegate);
+
+        DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
+                .addRegisteredFeatureTag(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG)
+                .addRegisteringFeatureTags(registeringTags)
+                .addDeregisteringFeatureTag(ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG,
+                        DelegateRegistrationState.DEREGISTERING_REASON_PROVISIONING_CHANGE)
+                .addDeregisteredFeatureTag(ImsSignallingUtils.GROUP_CHAT_TAG,
+                        DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
+                .build();
+        stateTracker.onRegistrationStateChanged(regState);
+
+        // Verify registration state through the process:
+        ArgumentCaptor<DelegateRegistrationState> regCaptor =
+                ArgumentCaptor.forClass(DelegateRegistrationState.class);
+        verify(mAppCallback, times(1)).onFeatureTagStatusChanged(
+                regCaptor.capture(), eq(new ArrayList<>(deniedTags)));
+        List<DelegateRegistrationState> testStates = regCaptor.getAllValues();
+
+        assertEquals(regState, testStates.get(0));
+        verify(mAppCallback).onCreated(mSipDelegate);
+    }
+
+
+    /**
      * Test the case that when the underlying Denied tags change in the SipDelegate, the change is
      * properly shown in the registration update event.
      */
     @SmallTest
     @Test
     public void testDelegateChangingDeniedTagsChanged() throws Exception {
-        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
-                mSipDelegate, mRcsStats);
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID,
+                Binder.getCallingUid(), mAppCallback, mSipDelegate, mRcsStats);
         Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
         Set<String> supportedTags = getSupportedTags();
         stateTracker.sipDelegateConnected(supportedTags, deniedTags);
@@ -255,8 +383,8 @@
     @SmallTest
     @Test
     public void testDelegateChangingDeniedTagsChangingToDestroy() throws Exception {
-        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
-                mSipDelegate, mRcsStats);
+        DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID,
+                Binder.getCallingUid(), mAppCallback, mSipDelegate, mRcsStats);
         Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
         Set<String> supportedTags = getSupportedTags();
         stateTracker.sipDelegateConnected(supportedTags, deniedTags);
@@ -316,4 +444,11 @@
         supportedTags.add(ImsSignallingUtils.GROUP_CHAT_TAG);
         return supportedTags;
     }
+
+    private Set<String> getRegisteringTag() {
+        Set<String> registeringTags = new ArraySet<>();
+        registeringTags.add(ImsSignallingUtils.CHATBOT_COMMUNICATION_USING_SESSION_TAG);
+        return registeringTags;
+
+    }
 }
diff --git a/tests/src/com/android/services/telephony/rcs/ImsSignallingUtils.java b/tests/src/com/android/services/telephony/rcs/ImsSignallingUtils.java
index d607f6d..0e725e0 100644
--- a/tests/src/com/android/services/telephony/rcs/ImsSignallingUtils.java
+++ b/tests/src/com/android/services/telephony/rcs/ImsSignallingUtils.java
@@ -28,4 +28,6 @@
             "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gppservice.ims.icsi.oma.cpm.session\"";
     public static final String FILE_TRANSFER_HTTP_TAG =
             "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gppapplication.ims.iari.rcs.fthttp\"";
+    public static final String CHATBOT_COMMUNICATION_USING_SESSION_TAG =
+            "+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gpp-application.ims.iari.rcs.chatbot\"";
 }
diff --git a/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java b/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java
index 78f6894..575b81e 100644
--- a/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java
@@ -30,6 +30,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.os.Binder;
 import android.telephony.ims.DelegateRegistrationState;
 import android.telephony.ims.DelegateRequest;
 import android.telephony.ims.FeatureTagState;
@@ -291,8 +292,8 @@
 
     private SipDelegateController getTestDelegateController(DelegateRequest request,
             Set<FeatureTagState> deniedSet) {
-        return new SipDelegateController(TEST_SUB_ID, request, "", mExecutorService,
-                mMockMessageTracker, mMockDelegateStateTracker,
+        return new SipDelegateController(TEST_SUB_ID, Binder.getCallingUid(), request, "",
+                mExecutorService, mMockMessageTracker, mMockDelegateStateTracker,
                 (a, b, deniedFeatureSet, d, e) ->  {
                     assertEquals(deniedSet, deniedFeatureSet);
                     return mMockBinderConnection;
diff --git a/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java b/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
index 0f139f8..42a45f4 100644
--- a/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
@@ -78,6 +78,7 @@
 @RunWith(AndroidJUnit4.class)
 public class SipTransportControllerTest extends TelephonyTestBase {
     private static final int TEST_SUB_ID = 1;
+    private static final int TEST_UID = 1001;
     private static final String TEST_PACKAGE_NAME = "com.test_pkg";
     private static final String TEST_PACKAGE_NAME_2 = "com.test_pkg2";
     private static final int TIMEOUT_MS = 200;
@@ -132,13 +133,13 @@
         mSmsPackageName.add(TEST_PACKAGE_NAME);
         doAnswer(invocation -> {
             Integer subId = invocation.getArgument(0);
-            String packageName = invocation.getArgument(2);
-            DelegateRequest request = invocation.getArgument(1);
+            String packageName = invocation.getArgument(3);
+            DelegateRequest request = invocation.getArgument(2);
             SipDelegateController c = getMockDelegateController(subId, packageName, request);
             assertNotNull("create called with no corresponding controller set up", c);
             return c;
-        }).when(mMockDelegateControllerFactory).create(anyInt(), any(), anyString(), any(), any(),
-                any(), any(), any());
+        }).when(mMockDelegateControllerFactory).create(anyInt(), anyInt(), any(), anyString(),
+                any(), any(), any(), any(), any());
         setFeatureAllowedConfig(TEST_SUB_ID, new String[]{ImsSignallingUtils.MMTEL_TAG,
                 ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG, ImsSignallingUtils.GROUP_CHAT_TAG,
                 ImsSignallingUtils.FILE_TRANSFER_HTTP_TAG});
@@ -254,7 +255,7 @@
         doReturn(mSipTransport).when(mRcsManager).getSipTransport();
         controller.onRcsConnected(mRcsManager);
         try {
-            controller.createSipDelegate(TEST_SUB_ID + 1,
+            controller.createSipDelegate(TEST_SUB_ID + 1, TEST_UID,
                     new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME,
                     mock(ISipDelegateConnectionStateCallback.class),
                     mock(ISipDelegateMessageCallback.class));
@@ -271,7 +272,7 @@
         doReturn(null).when(mRcsManager).getSipTransport();
         controller.onRcsConnected(mRcsManager);
         try {
-            controller.createSipDelegate(TEST_SUB_ID,
+            controller.createSipDelegate(TEST_SUB_ID, TEST_UID,
                     new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME,
                     mock(ISipDelegateConnectionStateCallback.class),
                     mock(ISipDelegateMessageCallback.class));
@@ -289,7 +290,7 @@
                 .when(mRcsManager).getSipTransport();
         // No RCS connected message
         try {
-            controller.createSipDelegate(TEST_SUB_ID,
+            controller.createSipDelegate(TEST_SUB_ID, TEST_UID,
                     new DelegateRequest(Collections.emptySet()), TEST_PACKAGE_NAME,
                     mock(ISipDelegateConnectionStateCallback.class),
                     mock(ISipDelegateMessageCallback.class));
@@ -812,7 +813,7 @@
         CompletableFuture<Boolean> pendingChange = setChangeSupportedFeatureTagsFuture(
                 delegateControllerContainer.delegateController, allowedTags, deniedTags);
         try {
-            controller.createSipDelegate(delegateControllerContainer.subId,
+            controller.createSipDelegate(delegateControllerContainer.subId, TEST_UID,
                     delegateControllerContainer.delegateRequest,
                     delegateControllerContainer.packageName,
                     delegateControllerContainer.mockDelegateConnectionCallback,