Add RCS metrics of sipDelegate/sipDelegateFeatureTags

Add RCS metrics of sipDelegate and sipDelegateFeatureTags
-SipDelegate: creation, destruction events
-SipDelegateFeatureTags: the states change evnets

Bug: http://b/174871215
Test: atest DelegateStateTrackerTest
Change-Id: I69bbae4b3d536f5da37362b1867f4488c43a49f2
diff --git a/src/com/android/services/telephony/rcs/DelegateStateTracker.java b/src/com/android/services/telephony/rcs/DelegateStateTracker.java
index 321c7ba..18aab88 100644
--- a/src/com/android/services/telephony/rcs/DelegateStateTracker.java
+++ b/src/com/android/services/telephony/rcs/DelegateStateTracker.java
@@ -24,9 +24,12 @@
 import android.telephony.ims.aidl.ISipDelegate;
 import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
 import android.telephony.ims.stub.DelegateConnectionStateCallback;
+import android.util.ArraySet;
 import android.util.LocalLog;
 import android.util.Log;
 
+import com.android.internal.telephony.metrics.RcsStats;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -50,11 +53,15 @@
     private boolean mCreatedCalled = false;
     private int mRegistrationStateOverride = -1;
 
+    private Set<String> mDelegateSupportedTags;
+    private final RcsStats mRcsStats;
+
     public DelegateStateTracker(int subId, ISipDelegateConnectionStateCallback appStateCallback,
-            ISipDelegate localDelegateImpl) {
+            ISipDelegate localDelegateImpl, RcsStats rcsStats) {
         mSubId = subId;
         mAppStateCallback = appStateCallback;
         mLocalDelegateImpl = localDelegateImpl;
+        mRcsStats = rcsStats;
     }
 
     /**
@@ -63,10 +70,13 @@
      * Registration and state updates will be send via the
      * {@link SipDelegateBinderConnection.StateCallback} callback implemented by this class as they
      * arrive.
+     * @param supportedTags the tags supported by the SipTransportController and ImsService creating
+     *                      the SipDelegate. These tags will be used as a key for SipDelegate
+     *                      metrics.
      * @param deniedTags The tags denied by the SipTransportController and ImsService creating the
      *         SipDelegate. These tags will need to be notified back to the IMS application.
      */
-    public void sipDelegateConnected(Set<FeatureTagState> deniedTags) {
+    public void sipDelegateConnected(Set<String> supportedTags, Set<FeatureTagState> deniedTags) {
         logi("SipDelegate connected with denied tags:" + deniedTags);
         // From the IMS application perspective, we only call onCreated/onDestroyed once and
         // provide the local implementation of ISipDelegate, which doesn't change, even though
@@ -74,6 +84,8 @@
         if (!mCreatedCalled) {
             mCreatedCalled = true;
             notifySipDelegateCreated();
+            mDelegateSupportedTags = supportedTags;
+            mRcsStats.createSipDelegateStats(mSubId, mDelegateSupportedTags);
         }
         mRegistrationStateOverride = -1;
         mDelegateDeniedTags = new ArrayList<>(deniedTags);
@@ -84,8 +96,8 @@
      *
      * This will trigger an override of the IMS application's registration state. All feature tags
      * in the REGISTERED state will be overridden to move to the deregistering state specified until
-     * a new SipDelegate was successfully created and {@link #sipDelegateConnected(Set)} was called
-     * or it was destroyed and {@link #sipDelegateDestroyed(int)} was called.
+     * a new SipDelegate was successfully created and {@link #sipDelegateConnected(Set, Set)} was
+     * called or it was destroyed and {@link #sipDelegateDestroyed(int)} was called.
      * @param deregisteringReason The new deregistering reason that all feature tags in the
      *         registered state should now report.
      */
@@ -115,6 +127,7 @@
         mRegistrationStateOverride = -1;
         try {
             mAppStateCallback.onDestroyed(reason);
+            mRcsStats.onSipDelegateStats(mSubId, mDelegateSupportedTags, reason);
         } catch (RemoteException e) {
             logw("sipDelegateDestroyed: IMS application is dead: " + e);
         }
@@ -141,6 +154,11 @@
         logi("onRegistrationStateChanged: sending reg state " + registrationState);
         try {
             mAppStateCallback.onFeatureTagStatusChanged(registrationState, mDelegateDeniedTags);
+            Set<String> registeredFeatureTags = registrationState.getRegisteredFeatureTags();
+            mRcsStats.onSipTransportFeatureTagStats(mSubId,
+                    new ArraySet<FeatureTagState>(mDelegateDeniedTags),
+                    registrationState.getDeregisteredFeatureTags(),
+                    registeredFeatureTags);
         } catch (RemoteException e) {
             logw("onRegistrationStateChanged: IMS application is dead: " + e);
         }
diff --git a/src/com/android/services/telephony/rcs/SipDelegateController.java b/src/com/android/services/telephony/rcs/SipDelegateController.java
index 8cc70a4..c728141 100644
--- a/src/com/android/services/telephony/rcs/SipDelegateController.java
+++ b/src/com/android/services/telephony/rcs/SipDelegateController.java
@@ -34,6 +34,7 @@
 import android.util.Pair;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.metrics.RcsStats;
 import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.PrintWriter;
@@ -102,7 +103,7 @@
         mMessageTransportWrapper = new MessageTransportWrapper(mSubId, executorService,
                 messageCallback);
         mDelegateStateTracker = new DelegateStateTracker(mSubId, stateCallback,
-                mMessageTransportWrapper.getDelegateConnection());
+                mMessageTransportWrapper.getDelegateConnection(), RcsStats.getInstance());
     }
 
     /**
@@ -191,7 +192,7 @@
                     .collect(Collectors.toSet()));
             mMessageTransportWrapper.openTransport(resultPair.first, allowedTags,
                     resultPair.second);
-            mDelegateStateTracker.sipDelegateConnected(resultPair.second);
+            mDelegateStateTracker.sipDelegateConnected(allowedTags, resultPair.second);
             return true;
         });
     }
diff --git a/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java b/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java
index 8236f44..25b5339 100644
--- a/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/DelegateStateTrackerTest.java
@@ -37,6 +37,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.TelephonyTestBase;
+import com.android.internal.telephony.metrics.RcsStats;
 
 import org.junit.After;
 import org.junit.Before;
@@ -56,6 +57,7 @@
 
     @Mock private ISipDelegate mSipDelegate;
     @Mock private ISipDelegateConnectionStateCallback mAppCallback;
+    @Mock private RcsStats mRcsStats;
 
     @Before
     public void setUp() throws Exception {
@@ -76,12 +78,14 @@
     @Test
     public void testDelegateCreated() throws Exception {
         DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
-                mSipDelegate);
+                mSipDelegate, mRcsStats);
         Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
-        stateTracker.sipDelegateConnected(deniedTags);
+        Set<String> supportedTags = getSupportedTags();
+        stateTracker.sipDelegateConnected(supportedTags, deniedTags);
         // Calling connected multiple times should not generate multiple onCreated events.
-        stateTracker.sipDelegateConnected(deniedTags);
+        stateTracker.sipDelegateConnected(supportedTags, deniedTags);
         verify(mAppCallback).onCreated(mSipDelegate);
+        verify(mRcsStats).createSipDelegateStats(TEST_SUB_ID, supportedTags);
 
         // Ensure status updates are sent to app as expected.
         DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
@@ -97,8 +101,10 @@
         stateTracker.onConfigurationChanged(c);
         verify(mAppCallback).onFeatureTagStatusChanged(eq(regState),
                 eq(new ArrayList<>(deniedTags)));
+        verify(mRcsStats).onSipTransportFeatureTagStats(TEST_SUB_ID, deniedTags,
+                regState.getDeregisteredFeatureTags(),
+                regState.getRegisteredFeatureTags());
         verify(mAppCallback).onConfigurationChanged(c);
-
         verify(mAppCallback, never()).onDestroyed(anyInt());
     }
 
@@ -109,14 +115,18 @@
     @Test
     public void testDelegateDestroyed() throws Exception {
         DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
-                mSipDelegate);
+                mSipDelegate, mRcsStats);
         Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
-        stateTracker.sipDelegateConnected(deniedTags);
+        Set<String> supportedTags = getSupportedTags();
+        stateTracker.sipDelegateConnected(supportedTags, deniedTags);
+        verify(mRcsStats).createSipDelegateStats(eq(TEST_SUB_ID), eq(supportedTags));
 
         stateTracker.sipDelegateDestroyed(
                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
         verify(mAppCallback).onDestroyed(
                 SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+        verify(mRcsStats).onSipDelegateStats(eq(TEST_SUB_ID), eq(supportedTags),
+                eq(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP));
     }
 
     /**
@@ -130,9 +140,10 @@
     @Test
     public void testDelegateChangingRegisteredTagsOverride() throws Exception {
         DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
-                mSipDelegate);
+                mSipDelegate, mRcsStats);
         Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
-        stateTracker.sipDelegateConnected(deniedTags);
+        Set<String> supportedTags = getSupportedTags();
+        stateTracker.sipDelegateConnected(supportedTags, deniedTags);
         // SipDelegate created
         verify(mAppCallback).onCreated(mSipDelegate);
         DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
@@ -158,7 +169,7 @@
                         DelegateRegistrationState.DEREGISTERED_REASON_NOT_PROVISIONED)
                 .build();
         // new underlying SipDelegate created
-        stateTracker.sipDelegateConnected(deniedTags);
+        stateTracker.sipDelegateConnected(supportedTags, deniedTags);
         stateTracker.onRegistrationStateChanged(regState);
 
         // Verify registration state through the process:
@@ -187,9 +198,10 @@
     @Test
     public void testDelegateChangingDeniedTagsChanged() throws Exception {
         DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
-                mSipDelegate);
+                mSipDelegate, mRcsStats);
         Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
-        stateTracker.sipDelegateConnected(deniedTags);
+        Set<String> supportedTags = getSupportedTags();
+        stateTracker.sipDelegateConnected(supportedTags, deniedTags);
         // SipDelegate created
         verify(mAppCallback).onCreated(mSipDelegate);
         DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
@@ -220,7 +232,7 @@
         // new underlying SipDelegate created, but SipDelegate denied one to one chat
         deniedTags.add(new FeatureTagState(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG,
                 SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
-        stateTracker.sipDelegateConnected(deniedTags);
+        stateTracker.sipDelegateConnected(supportedTags, deniedTags);
         DelegateRegistrationState fullyDeniedRegState = new DelegateRegistrationState.Builder()
                 .build();
         // In this special case, it will be the SipDelegateConnectionBase that will trigger
@@ -244,9 +256,10 @@
     @Test
     public void testDelegateChangingDeniedTagsChangingToDestroy() throws Exception {
         DelegateStateTracker stateTracker = new DelegateStateTracker(TEST_SUB_ID, mAppCallback,
-                mSipDelegate);
+                mSipDelegate, mRcsStats);
         Set<FeatureTagState> deniedTags = getMmTelDeniedTag();
-        stateTracker.sipDelegateConnected(deniedTags);
+        Set<String> supportedTags = getSupportedTags();
+        stateTracker.sipDelegateConnected(supportedTags, deniedTags);
         // SipDelegate created
         verify(mAppCallback).onCreated(mSipDelegate);
         DelegateRegistrationState regState = new DelegateRegistrationState.Builder()
@@ -296,4 +309,11 @@
                 SipDelegateManager.DENIED_REASON_NOT_ALLOWED));
         return deniedTags;
     }
+
+    private Set<String> getSupportedTags() {
+        Set<String> supportedTags = new ArraySet<>();
+        supportedTags.add(ImsSignallingUtils.ONE_TO_ONE_CHAT_TAG);
+        supportedTags.add(ImsSignallingUtils.GROUP_CHAT_TAG);
+        return supportedTags;
+    }
 }
diff --git a/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java b/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java
index 5b0e7c5..78f6894 100644
--- a/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/SipDelegateControllerTest.java
@@ -107,7 +107,8 @@
         assertTrue(future.get());
         verify(mMockMessageTracker).openTransport(mMockSipDelegate, request.getFeatureTags(),
                 Collections.emptySet());
-        verify(mMockDelegateStateTracker).sipDelegateConnected(Collections.emptySet());
+        verify(mMockDelegateStateTracker).sipDelegateConnected(request.getFeatureTags(),
+                Collections.emptySet());
     }
 
     @SmallTest
@@ -138,7 +139,7 @@
         allowedTags.removeAll(deniedTags.stream().map(FeatureTagState::getFeatureTag)
                 .collect(Collectors.toSet()));
         verify(mMockMessageTracker).openTransport(mMockSipDelegate, allowedTags, deniedTags);
-        verify(mMockDelegateStateTracker).sipDelegateConnected(deniedTags);
+        verify(mMockDelegateStateTracker).sipDelegateConnected(allowedTags, deniedTags);
     }
 
     @SmallTest
@@ -249,7 +250,9 @@
                 Collections.emptySet());
         verify(mMockMessageTracker).openTransport(mMockSipDelegate, newFts,
                 Collections.emptySet());
-        verify(mMockDelegateStateTracker, times(2)).sipDelegateConnected(Collections.emptySet());
+        verify(mMockDelegateStateTracker).sipDelegateConnected(
+                request.getFeatureTags(), Collections.emptySet());
+        verify(mMockDelegateStateTracker).sipDelegateConnected(newFts, Collections.emptySet());
     }
 
     private void createSipDelegate(DelegateRequest request, SipDelegateController controller)