Add video call support for telecom metrics

Flag: com.android.server.telecom.flags.telecom_metrics_support
Bug: 400761451
Test: manual
Test: atest TeleServiceTests
Change-Id: I682c2f5f370c127eb32b530bc64e1cb9876cb0d6
diff --git a/proto/pulled_atoms.proto b/proto/pulled_atoms.proto
index 2916dad..a72e847 100644
--- a/proto/pulled_atoms.proto
+++ b/proto/pulled_atoms.proto
@@ -59,6 +59,9 @@
     // DUAL_DIFF_ACCOUNT, etc.
     // From frameworks/proto_logging/stats/enums/telecomm/enums.proto
     optional int32 simultaneous_type = 10;
+
+    // True if it is a video call
+    optional bool video_call = 11;
 }
 
 /**
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 8cd5266..aceabed 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -510,6 +510,11 @@
      */
     private int mSimultaneousType = CALL_SIMULTANEOUS_UNKNOWN;
 
+    /**
+     * Indicate whether the call has the video
+     */
+    boolean mHasVideoCall;
+
     private Bundle mIntentExtras = new Bundle();
 
     /**
@@ -4317,6 +4322,7 @@
         }
 
         if (VideoProfile.isVideo(videoState)) {
+            mHasVideoCall = true;
             mAnalytics.setCallIsVideo(true);
         }
     }
@@ -5088,4 +5094,8 @@
     public int getSimultaneousType() {
         return mSimultaneousType;
     }
+
+    public boolean hasVideoCall() {
+        return mHasVideoCall;
+    }
 }
diff --git a/src/com/android/server/telecom/metrics/CallStats.java b/src/com/android/server/telecom/metrics/CallStats.java
index 5f00446..41de0d1 100644
--- a/src/com/android/server/telecom/metrics/CallStats.java
+++ b/src/com/android/server/telecom/metrics/CallStats.java
@@ -84,7 +84,7 @@
                             v.getCallDirection(), v.getExternalCall(), v.getEmergencyCall(),
                             v.getMultipleAudioAvailable(), v.getAccountType(), v.getUid(),
                             v.getCount(), v.getAverageDurationMs(), v.getDisconnectCause(),
-                            v.getSimultaneousType())));
+                            v.getSimultaneousType(), v.getVideoCall())));
             mCallStatsMap.clear();
             onAggregate();
             return StatsManager.PULL_SUCCESS;
@@ -101,7 +101,8 @@
                 mCallStatsMap.put(new CallStatsKey(v.getCallDirection(),
                         v.getExternalCall(), v.getEmergencyCall(),
                         v.getMultipleAudioAvailable(), v.getAccountType(),
-                        v.getUid(), v.getDisconnectCause(), v.getSimultaneousType()),
+                        v.getUid(), v.getDisconnectCause(), v.getSimultaneousType(),
+                        v.getVideoCall()),
                         new CallStatsData(
                                 v.getCount(), v.getAverageDurationMs()));
             }
@@ -130,6 +131,7 @@
             mPulledAtoms.callStats[index[0]].setUid(k.mUid);
             mPulledAtoms.callStats[index[0]].setDisconnectCause(k.mCause);
             mPulledAtoms.callStats[index[0]].setSimultaneousType(k.mSimultaneousType);
+            mPulledAtoms.callStats[index[0]].setVideoCall(k.mHasVideoCall);
             mPulledAtoms.callStats[index[0]].setCount(v.mCount);
             mPulledAtoms.callStats[index[0]].setAverageDurationMs(v.mAverageDuration);
             index[0]++;
@@ -140,14 +142,16 @@
     public void log(int direction, boolean isExternal, boolean isEmergency,
         boolean isMultipleAudioAvailable, int accountType, int uid, int duration) {
         log(direction, isExternal, isEmergency, isMultipleAudioAvailable, accountType, uid,
-                0, 0, duration);
+                0, 0, false, duration);
     }
+
     public void log(int direction, boolean isExternal, boolean isEmergency,
             boolean isMultipleAudioAvailable, int accountType, int uid,
-            int disconnectCause, int simultaneousType, int duration) {
+            int disconnectCause, int simultaneousType, boolean hasVideoCall, int duration) {
         post(() -> {
             CallStatsKey key = new CallStatsKey(direction, isExternal, isEmergency,
-                    isMultipleAudioAvailable, accountType, uid, disconnectCause, simultaneousType);
+                    isMultipleAudioAvailable, accountType, uid, disconnectCause, simultaneousType,
+                    hasVideoCall);
             CallStatsData data = mCallStatsMap.computeIfAbsent(key, k -> new CallStatsData(0, 0));
             data.add(duration);
             onAggregate();
@@ -183,7 +187,7 @@
 
             log(direction, call.isExternalCall(), call.isEmergencyCall(), hasMultipleAudioDevices,
                     accountType, uid, call.getDisconnectCause().getCode(),
-                    call.getSimultaneousType(), duration);
+                    call.getSimultaneousType(), call.hasVideoCall(), duration);
         });
     }
 
@@ -250,16 +254,17 @@
         final int mUid;
         final int mCause;
         final int mSimultaneousType;
+        final boolean mHasVideoCall;
 
         CallStatsKey(int direction, boolean isExternal, boolean isEmergency,
             boolean isMultipleAudioAvailable, int accountType, int uid) {
             this(direction, isExternal, isEmergency, isMultipleAudioAvailable, accountType, uid,
-                    0, 0);
+                    0, 0, false);
         }
 
         CallStatsKey(int direction, boolean isExternal, boolean isEmergency,
                 boolean isMultipleAudioAvailable, int accountType, int uid,
-                int cause, int simultaneousType) {
+                int cause, int simultaneousType, boolean hasVideoCall) {
             mDirection = direction;
             mIsExternal = isExternal;
             mIsEmergency = isEmergency;
@@ -268,6 +273,7 @@
             mUid = uid;
             mCause = cause;
             mSimultaneousType = simultaneousType;
+            mHasVideoCall = hasVideoCall;
         }
 
         @Override
@@ -282,13 +288,14 @@
                     && this.mIsEmergency == obj.mIsEmergency
                     && this.mIsMultipleAudioAvailable == obj.mIsMultipleAudioAvailable
                     && this.mAccountType == obj.mAccountType && this.mUid == obj.mUid
-                    && this.mCause == obj.mCause && this.mSimultaneousType == obj.mSimultaneousType;
+                    && this.mCause == obj.mCause && this.mSimultaneousType == obj.mSimultaneousType
+                    && this.mHasVideoCall == obj.mHasVideoCall;
         }
 
         @Override
         public int hashCode() {
             return Objects.hash(mDirection, mIsExternal, mIsEmergency, mIsMultipleAudioAvailable,
-                    mAccountType, mUid, mCause, mSimultaneousType);
+                    mAccountType, mUid, mCause, mSimultaneousType, mHasVideoCall);
         }
 
         @Override
@@ -296,7 +303,8 @@
             return "[CallStatsKey: mDirection=" + mDirection + ", mIsExternal=" + mIsExternal
                     + ", mIsEmergency=" + mIsEmergency + ", mIsMultipleAudioAvailable="
                     + mIsMultipleAudioAvailable + ", mAccountType=" + mAccountType + ", mUid="
-                    + mUid + ", mCause=" + mCause + ", mScType=" + mSimultaneousType + "]";
+                    + mUid + ", mCause=" + mCause + ", mScType=" + mSimultaneousType
+                    + ", mHasVideoCall =" + mHasVideoCall + "]";
         }
     }
 
diff --git a/tests/src/com/android/server/telecom/tests/TelecomPulledAtomTest.java b/tests/src/com/android/server/telecom/tests/TelecomPulledAtomTest.java
index 875617f..0859ec4 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomPulledAtomTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomPulledAtomTest.java
@@ -694,6 +694,7 @@
         doReturn(true).when(call).isIncoming();
         doReturn(new DisconnectCause(0)).when(call).getDisconnectCause();
         doReturn(0).when(call).getSimultaneousType();
+        doReturn(false).when(call).hasVideoCall();
         doReturn(account).when(call).getPhoneAccountFromHandle();
         doReturn((long) duration).when(call).getAgeMillis();
         doReturn(false).when(account).hasCapabilities(eq(PhoneAccount.CAPABILITY_SELF_MANAGED));
@@ -711,7 +712,7 @@
 
         verify(callStats, times(1)).log(eq(CALL_STATS__CALL_DIRECTION__DIR_INCOMING),
                 eq(false), eq(false), eq(false), eq(CALL_STATS__ACCOUNT_TYPE__ACCOUNT_SIM),
-                eq(fakeUid), eq(0), eq(0), eq(duration));
+                eq(fakeUid), eq(0), eq(0), eq(false), eq(duration));
     }
 
     @Test
@@ -734,6 +735,7 @@
         doReturn(true).when(call).isIncoming();
         doReturn(new DisconnectCause(0)).when(call).getDisconnectCause();
         doReturn(0).when(call).getSimultaneousType();
+        doReturn(false).when(call).hasVideoCall();
         doReturn(account).when(call).getPhoneAccountFromHandle();
         doReturn((long) duration).when(call).getAgeMillis();
         doReturn(false).when(account).hasCapabilities(eq(PhoneAccount.CAPABILITY_SELF_MANAGED));
@@ -754,7 +756,7 @@
 
         verify(callStats, times(1)).log(eq(CALL_STATS__CALL_DIRECTION__DIR_INCOMING),
                 eq(false), eq(false), eq(true), eq(CALL_STATS__ACCOUNT_TYPE__ACCOUNT_SIM),
-                eq(fakeUid), eq(0), eq(0), eq(duration));
+                eq(fakeUid), eq(0), eq(0), eq(false), eq(duration));
     }
 
     @Test