Merge "Add RCS metrics for provisioning event" into sc-v2-dev am: 9e62f2bc3d

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telephony/+/16264342

Change-Id: I455d668231b1388c419d7ae19c85599c39568e46
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 14a6356..913a4a6 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -22,6 +22,7 @@
 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_GSM;
 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_IMS;
 import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
+import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__CLIENT_PARAMS_SENT;
 
 import android.Manifest;
 import android.Manifest.permission;
@@ -181,6 +182,7 @@
 import com.android.internal.telephony.ims.ImsResolver;
 import com.android.internal.telephony.imsphone.ImsPhone;
 import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
+import com.android.internal.telephony.metrics.RcsStats;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
 import com.android.internal.telephony.uicc.IccIoResult;
@@ -10392,6 +10394,9 @@
             } else {
                 configBinder.setRcsClientConfiguration(rcc);
             }
+
+            RcsStats.getInstance().onRcsClientProvisioningStats(subId,
+                    RCS_CLIENT_PROVISIONING_STATS__EVENT__CLIENT_PARAMS_SENT);
         } catch (RemoteException e) {
             Rlog.e(LOG_TAG, "fail to setRcsClientConfiguration " + e.getMessage());
             throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
index 6d2bd6f..e819afc 100644
--- a/src/com/android/phone/RcsProvisioningMonitor.java
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -16,6 +16,10 @@
 
 package com.android.phone;
 
+import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML;
+import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__DMA_CHANGED;
+import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION;
+
 import android.Manifest;
 import android.app.role.OnRoleHoldersChangedListener;
 import android.app.role.RoleManager;
@@ -47,6 +51,8 @@
 import com.android.ims.FeatureUpdates;
 import com.android.ims.RcsFeatureManager;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.metrics.RcsStats;
+import com.android.internal.telephony.metrics.RcsStats.RcsProvisioningCallback;
 import com.android.internal.telephony.util.HandlerExecutor;
 import com.android.internal.util.CollectionUtils;
 import com.android.telephony.Rlog;
@@ -100,6 +106,8 @@
     private final RoleManagerAdapter mRoleManager;
     private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory;
 
+    private RcsStats mRcsStats;
+
     private static RcsProvisioningMonitor sInstance;
 
     private final SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener =
@@ -227,6 +235,10 @@
             if (mSingleRegistrationCapability != singleRegistrationCapability) {
                 mSingleRegistrationCapability = singleRegistrationCapability;
                 notifyDma();
+
+                // update whether single registration supported.
+                mRcsStats.setEnableSingleRegistration(mSubId,
+                        mSingleRegistrationCapability == ProvisioningManager.STATUS_CAPABLE);
             }
         }
 
@@ -338,6 +350,9 @@
                     } else {
                         notifyRcsAutoConfigurationReceived();
                     }
+
+                    // check callback for metrics if not registered, register callback
+                    registerMetricsCallback();
                 } else {
                     // clear callbacks if rcs disconnected
                     clearCallbacks();
@@ -397,6 +412,18 @@
                 }
             }
         }
+
+        private void registerMetricsCallback() {
+            RcsProvisioningCallback rcsProvisioningCallback = mRcsStats.getRcsProvisioningCallback(
+                    mSubId, mSingleRegistrationCapability == ProvisioningManager.STATUS_CAPABLE);
+
+            // if not yet registered, register callback and set registered value
+            if (rcsProvisioningCallback != null && !rcsProvisioningCallback.getRegistered()) {
+                if (addRcsConfigCallback(rcsProvisioningCallback)) {
+                    rcsProvisioningCallback.setRegistered(true);
+                }
+            }
+        }
     }
 
     @VisibleForTesting
@@ -454,7 +481,7 @@
 
     @VisibleForTesting
     public RcsProvisioningMonitor(PhoneGlobals app, Looper looper, RoleManagerAdapter roleManager,
-            FeatureConnectorFactory<RcsFeatureManager> factory) {
+            FeatureConnectorFactory<RcsFeatureManager> factory, RcsStats rcsStats) {
         mPhone = app;
         mHandler = new MyHandler(looper);
         mCarrierConfigManager = mPhone.getSystemService(CarrierConfigManager.class);
@@ -465,6 +492,7 @@
         logv("DMA is " + mDmaPackageName);
         mDmaChangedListener = new DmaChangedListener();
         mFeatureFactory = factory;
+        mRcsStats = rcsStats;
         init();
     }
 
@@ -477,7 +505,8 @@
             HandlerThread handlerThread = new HandlerThread(TAG);
             handlerThread.start();
             sInstance = new RcsProvisioningMonitor(app, handlerThread.getLooper(),
-                    new RoleManagerAdapterImpl(app), RcsFeatureManager::getConnector);
+                    new RoleManagerAdapterImpl(app), RcsFeatureManager::getConnector,
+                    RcsStats.getInstance());
         }
         return sInstance;
     }
@@ -704,6 +733,10 @@
                     logv("acs not used, set cached config and notify.");
                     v.setConfig(cachedConfig);
                 }
+
+                // store RCS metrics - DMA changed event
+                mRcsStats.onRcsClientProvisioningStats(k,
+                        RCS_CLIENT_PROVISIONING_STATS__EVENT__DMA_CHANGED);
             });
         }
     }
@@ -803,6 +836,14 @@
         }
         info.setConfig(isCompressed ? RcsConfig.decompressGzip(config) : config);
         updateConfigForSub(subId, config, isCompressed);
+
+        // Supporting ACS means config data comes from ACS
+        // store RCS metrics - received provisioning event
+        if (isAcsUsed(subId)) {
+            mRcsStats.onRcsAcsProvisioningStats(subId, 200,
+                    RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML,
+                    isRcsVolteSingleRegistrationEnabled(subId));
+        }
     }
 
     private void onReconfigRequest(int subId) {
@@ -814,6 +855,10 @@
             updateConfigForSub(subId, null, true);
             info.triggerRcsReconfiguration();
         }
+
+        // store RCS metrics - reconfig event
+        mRcsStats.onRcsClientProvisioningStats(subId,
+                RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION);
     }
 
     private void notifyDmaForSub(int subId, int capability) {
diff --git a/src/com/android/services/telephony/rcs/TelephonyRcsService.java b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
index e72b0ab..dfcea74 100644
--- a/src/com/android/services/telephony/rcs/TelephonyRcsService.java
+++ b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.PhoneConfigurationManager;
+import com.android.internal.telephony.metrics.RcsStats;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.phone.ImsStateCallbackController;
 import com.android.phone.R;
@@ -164,6 +165,7 @@
         mFeatureControllers = new SparseArray<>(numSlots);
         mSlotToAssociatedSubIds = new SparseArray<>(numSlots);
         mRcsUceEnabled = sResourceProxy.getDeviceUceEnabled(mContext);
+        RcsStats.getInstance().registerUceCallback();
     }
 
     @VisibleForTesting
@@ -174,6 +176,7 @@
         mSlotToAssociatedSubIds = new SparseArray<>(numSlots);
         sResourceProxy = resourceProxy;
         mRcsUceEnabled = sResourceProxy.getDeviceUceEnabled(mContext);
+        RcsStats.getInstance().registerUceCallback();
     }
 
     /**
diff --git a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
index 8e5e073..8873402 100644
--- a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
+++ b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
@@ -16,6 +16,10 @@
 
 package com.android.phone;
 
+import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML;
+import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__DMA_CHANGED;
+import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNull;
@@ -64,6 +68,7 @@
 import com.android.ims.FeatureConnector;
 import com.android.ims.RcsFeatureManager;
 import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.metrics.RcsStats;
 
 import org.junit.After;
 import org.junit.Before;
@@ -179,6 +184,10 @@
     private IRcsConfigCallback mCallback;
     @Mock
     private PackageManager mPackageManager;
+    @Mock
+    private RcsStats mRcsStats;
+    @Mock
+    private RcsStats.RcsProvisioningCallback mRcsProvisioningCallback;
 
     private Executor mExecutor = new Executor() {
         @Override
@@ -768,6 +777,66 @@
         assertNull(mRcsProvisioningMonitor.getImsFeatureValidationOverride(FAKE_SUB_ID_BASE));
     }
 
+    @Test
+    @SmallTest
+    public void testMetricsAcsNotUsed() throws Exception {
+        createMonitor(1);
+
+        // Not used ACS
+        mBundle.putBoolean(CarrierConfigManager.KEY_USE_ACS_FOR_RCS_BOOL, false);
+        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
+        processAllMessages();
+        mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, CONFIG_DEFAULT.getBytes(), false);
+        processAllMessages();
+        verify(mRcsStats, never()).onRcsAcsProvisioningStats(anyInt(), anyInt(),
+                anyInt(), anyBoolean());
+    }
+
+    @Test
+    @SmallTest
+    public void testMetricsAcsUsed() throws Exception {
+        when(mRcsStats.getRcsProvisioningCallback(anyInt(), anyBoolean()))
+                .thenReturn(mRcsProvisioningCallback);
+        createMonitor(1);
+
+        verify(mIImsConfig, times(1))
+                .notifyRcsAutoConfigurationReceived(any(), anyBoolean());
+        // verify RcsStats.getRcsProvisioningCallback() is called
+        verify(mRcsStats, times(1)).getRcsProvisioningCallback(
+                eq(FAKE_SUB_ID_BASE), anyBoolean());
+        // verify registered callback obj which comes from RcsStats.getRcsProvisioningCallback()
+        verify(mIImsConfig, times(1))
+                .addRcsConfigCallback(eq(mRcsProvisioningCallback));
+
+        // Config data received and ACS used
+        int errorCode = 200;
+        mBundle.putBoolean(CarrierConfigManager.KEY_USE_ACS_FOR_RCS_BOOL, true);
+        broadcastCarrierConfigChange(FAKE_SUB_ID_BASE);
+        processAllMessages();
+        mRcsProvisioningMonitor.updateConfig(FAKE_SUB_ID_BASE, CONFIG_DEFAULT.getBytes(), false);
+        processAllMessages();
+        verify(mRcsStats, times(1)).onRcsAcsProvisioningStats(eq(FAKE_SUB_ID_BASE), eq(errorCode),
+                eq(RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML), anyBoolean());
+    }
+
+    @Test
+    @SmallTest
+    public void testMetricsClientProvisioningStats() throws Exception {
+        createMonitor(1);
+
+        // reconfig trigger
+        mRcsProvisioningMonitor.requestReconfig(FAKE_SUB_ID_BASE);
+        processAllMessages();
+        verify(mRcsStats, times(1)).onRcsClientProvisioningStats(eq(FAKE_SUB_ID_BASE),
+                eq(RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION));
+
+        // DMA changed
+        updateDefaultMessageApplication(DEFAULT_MESSAGING_APP2);
+        processAllMessages();
+        verify(mRcsStats, times(1)).onRcsClientProvisioningStats(eq(FAKE_SUB_ID_BASE),
+                eq(RCS_CLIENT_PROVISIONING_STATS__EVENT__DMA_CHANGED));
+    }
+
     private void createMonitor(int subCount) throws Exception {
         if (Looper.myLooper() == null) {
             Looper.prepare();
@@ -777,7 +846,7 @@
                 .thenReturn(mFeatureConnector);
         when(mFeatureManager.getConfig()).thenReturn(mIImsConfig);
         mRcsProvisioningMonitor = new RcsProvisioningMonitor(mPhone, mHandlerThread.getLooper(),
-                mRoleManager, mFeatureFactory);
+                mRoleManager, mFeatureFactory, mRcsStats);
         mHandler = mRcsProvisioningMonitor.getHandler();
         try {
             mLooper = new TestableLooper(mHandler.getLooper());