Log Outgoing rejected/canceled VT calls as video

When placing a call that is rejected or canceled before
it went to active, we used to log those calls as audio calls.

This change fixes that bug and correctly logs these
canceled/rejected calls as video calls.

Test: Manual, telecom unit tests
Bug: 63099560
Change-Id: I8eff4c99d06a50c7d19ec3cfa08524cf1ad79ac2
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index ad9ac35..9ab5290 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -780,6 +780,8 @@
                 return;
             }
 
+            updateVideoHistoryViaState(mState, newState);
+
             mState = newState;
             maybeLoadCannedSmsResponses();
 
@@ -792,12 +794,6 @@
                     mAnalytics.setCallStartTime(mConnectTimeMillis);
                 }
 
-                // Video state changes are normally tracked against history when a call is active.
-                // When the call goes active we need to be sure we track the history in case the
-                // state never changes during the duration of the call -- we want to ensure we
-                // always know the state at the start of the call.
-                mVideoStateHistory = mVideoStateHistory | mVideoState;
-
                 // We're clearly not disconnected, so reset the disconnected time.
                 mDisconnectTimeMillis = 0;
             } else if (mState == CallState.DISCONNECTED) {
@@ -806,12 +802,6 @@
                 setLocallyDisconnecting(false);
                 fixParentAfterDisconnect();
             }
-            if (mState == CallState.DISCONNECTED &&
-                    (mDisconnectCause.getCode() == DisconnectCause.MISSED ||
-                            mDisconnectCause.getCode() == DisconnectCause.REJECTED)) {
-                // Ensure when an incoming call is missed that the video state history is updated.
-                mVideoStateHistory |= mVideoState;
-            }
 
             // Log the state transition event
             String event = null;
@@ -2487,13 +2477,14 @@
             videoState = VideoProfile.STATE_AUDIO_ONLY;
         }
 
-        // Track which video states were applicable over the duration of the call.
-        // Only track the call state when the call is active or disconnected.  This ensures we do
-        // not include the video state when:
+        // Track Video State history during the duration of the call.
+        // Only update the history when the call is active or disconnected. This ensures we do
+        // not include the video state history when:
         // - Call is incoming (but not answered).
         // - Call it outgoing (but not answered).
         // We include the video state when disconnected to ensure that rejected calls reflect the
         // appropriate video state.
+        // For all other times we add to the video state history, see #setState.
         if (isActive() || getState() == CallState.DISCONNECTED) {
             mVideoStateHistory = mVideoStateHistory | videoState;
         }
@@ -2740,4 +2731,21 @@
             l.onHandoverRequested(this, handoverToHandle, videoState, extras);
         }
     }
+
+    /**
+     * Sets the video history based on the state and state transitions of the call. Always add the
+     * current video state to the video state history during a call transition except for the
+     * transitions DIALING->ACTIVE and RINGING->ACTIVE. In these cases, clear the history. If a
+     * call starts dialing/ringing as a VT call and gets downgraded to audio, we need to record
+     * the history as an audio call.
+     */
+    private void updateVideoHistoryViaState(int oldState, int newState) {
+        if ((oldState == CallState.DIALING || oldState == CallState.RINGING)
+                && newState == CallState.ACTIVE) {
+            mVideoStateHistory = mVideoState;
+        }
+
+        mVideoStateHistory |= mVideoState;
+    }
+
 }
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 749f3c6..ce774a7 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -871,38 +871,6 @@
     }
 
     /**
-     * Ensure that when an incoming video call is missed, the video state history still includes
-     * video calling. This is important for the call log.
-     */
-    @LargeTest
-    public void testIncomingVideoCallMissedCheckVideoHistory() throws Exception {
-        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
-        com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
-                .iterator().next();
-
-        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.MISSED);
-
-        assertTrue(VideoProfile.isVideo(call.getVideoStateHistory()));
-    }
-
-    /**
-     * Ensure that when an incoming video call is rejected, the video state history still includes
-     * video calling. This is important for the call log.
-     */
-    @LargeTest
-    public void testIncomingVideoCallRejectedCheckVideoHistory() throws Exception {
-        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
-                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
-        com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
-                .iterator().next();
-
-        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.REJECTED);
-
-        assertTrue(VideoProfile.isVideo(call.getVideoStateHistory()));
-    }
-
-    /**
      * Test scenario where the user starts an outgoing video call with no selected PhoneAccount, and
      * then subsequently selects a PhoneAccount which does not support video calling.
      * @throws Exception
diff --git a/tests/src/com/android/server/telecom/tests/VideoCallTests.java b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
index 4764e92..c91f86e 100644
--- a/tests/src/com/android/server/telecom/tests/VideoCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/VideoCallTests.java
@@ -18,9 +18,12 @@
 
 import org.mockito.ArgumentCaptor;
 
+import android.os.Process;
 import android.os.RemoteException;
 import android.telecom.CallAudioState;
+import android.telecom.DisconnectCause;
 import android.telecom.VideoProfile;
+import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
 
 import com.android.server.telecom.CallAudioModeStateMachine;
@@ -127,6 +130,93 @@
     }
 
     /**
+     * Ensure that when an incoming video call is missed, the video state history still includes
+     * video calling. This is important for the call log.
+     */
+    @LargeTest
+    public void testIncomingVideoCallMissedCheckVideoHistory() throws Exception {
+        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+        com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
+                .iterator().next();
+
+        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.MISSED);
+
+        assertTrue(VideoProfile.isVideo(call.getVideoStateHistory()));
+    }
+
+    /**
+     * Ensure that when an incoming video call is rejected, the video state history still includes
+     * video calling. This is important for the call log.
+     */
+    @LargeTest
+    public void testIncomingVideoCallRejectedCheckVideoHistory() throws Exception {
+        IdPair ids = startIncomingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+                VideoProfile.STATE_BIDIRECTIONAL, mConnectionServiceFixtureA);
+        com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
+                .iterator().next();
+
+        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.REJECTED);
+
+        assertTrue(VideoProfile.isVideo(call.getVideoStateHistory()));
+    }
+
+
+    /**
+     * Ensure that when an outgoing video call is canceled, the video state history still includes
+     * video calling. This is important for the call log.
+     */
+    @LargeTest
+    public void testOutgoingVideoCallCanceledCheckVideoHistory() throws Exception {
+        IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+                mConnectionServiceFixtureA, Process.myUserHandle(),
+                VideoProfile.STATE_BIDIRECTIONAL);
+        com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
+                .iterator().next();
+
+        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
+
+        assertTrue(VideoProfile.isVideo(call.getVideoStateHistory()));
+    }
+
+    /**
+     * Ensure that when an outgoing video call is rejected, the video state history still includes
+     * video calling. This is important for the call log.
+     */
+    @LargeTest
+    public void testOutgoingVideoCallRejectedCheckVideoHistory() throws Exception {
+        IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+                mConnectionServiceFixtureA, Process.myUserHandle(),
+                VideoProfile.STATE_BIDIRECTIONAL);
+        com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
+                .iterator().next();
+
+        mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.REMOTE);
+
+        assertTrue(VideoProfile.isVideo(call.getVideoStateHistory()));
+    }
+
+    /**
+     * Ensure that when an outgoing video call is answered as audio only, the video state history
+     * shows that the call was audio only. This is important for the call log.
+     */
+    @LargeTest
+    public void testOutgoingVideoCallAnsweredAsAudio() throws Exception {
+        IdPair ids = startOutgoingPhoneCall("650-555-1212", mPhoneAccountA0.getAccountHandle(),
+                mConnectionServiceFixtureA, Process.myUserHandle(),
+                VideoProfile.STATE_BIDIRECTIONAL);
+        com.android.server.telecom.Call call = mTelecomSystem.getCallsManager().getCalls()
+                .iterator().next();
+
+        mConnectionServiceFixtureA.mConnectionById.get(ids.mConnectionId).videoState
+                = VideoProfile.STATE_AUDIO_ONLY;
+        mConnectionServiceFixtureA.sendSetVideoState(ids.mConnectionId);
+        mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
+
+        assertFalse(VideoProfile.isVideo(call.getVideoStateHistory()));
+    }
+
+    /**
      * Verifies that the
      * {@link android.telecom.InCallService#onCallAudioStateChanged(CallAudioState)} change is
      * called with an expected route and number of changes.