Make sure that IRemoteAnimationController is always triggered.

When an app transition is executed, RemoteAnimationTarget instance is
created for apps and IRemoteAnimationController#onAnimationStart is
called.
However it's possible that no valid app exists when an app transition is
executed, for example, an activity doesn't resume before timeout. If it
happens, RemoteAnimationController triggers
IRemoteAnimationController#onAnimationCancelled.

Test: atest RemoteAnimationControllerTest
Bug: 175687166
Change-Id: I50ddc91f7bd7ed24a977fa3face9c6e56e1bea02
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index b7bf8ab..b14db78 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -307,6 +307,12 @@
       "group": "WM_DEBUG_STARTING_WINDOW",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "-1777196134": {
+      "message": "goodToGo(): No apps to animate, mPendingAnimations=%d",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
+      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
+    },
     "-1770075711": {
       "message": "Adding window client %s that is dead, aborting.",
       "level": "WARN",
@@ -1981,12 +1987,6 @@
       "group": "WM_DEBUG_STATES",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
-    "194124419": {
-      "message": "goodToGo(): Animation finished already, canceled=%s mPendingAnimations=%d",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
-      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
-    },
     "200829729": {
       "message": "ScreenRotationAnimation onAnimationEnd",
       "level": "DEBUG",
@@ -2083,6 +2083,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DragState.java"
     },
+    "269976641": {
+      "message": "goodToGo(): Animation canceled already",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_REMOTE_ANIMATIONS",
+      "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
+    },
     "274773837": {
       "message": "applyAnimation: anim=%s nextAppTransition=ANIM_CLIP_REVEAL transit=%s Callers=%s",
       "level": "VERBOSE",
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 42cb96f..6fc585e 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -104,11 +104,11 @@
      */
     void goodToGo(@WindowManager.TransitionOldType int transit) {
         ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "goodToGo()");
-        if (mPendingAnimations.isEmpty() || mCanceled) {
+        if (mCanceled) {
             ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS,
-                    "goodToGo(): Animation finished already, canceled=%s mPendingAnimations=%d",
-                    mCanceled, mPendingAnimations.size());
+                    "goodToGo(): Animation canceled already");
             onAnimationFinished();
+            invokeAnimationCancelled();
             return;
         }
 
@@ -120,8 +120,11 @@
         // Create the app targets
         final RemoteAnimationTarget[] appTargets = createAppAnimations();
         if (appTargets.length == 0) {
-            ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "goodToGo(): No apps to animate");
+            ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS,
+                    "goodToGo(): No apps to animate, mPendingAnimations=%d",
+                    mPendingAnimations.size());
             onAnimationFinished();
+            invokeAnimationCancelled();
             return;
         }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 2fdd63e..c98e013 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -36,6 +36,8 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 
@@ -208,18 +210,20 @@
     }
 
     @Test
-    public void testZeroAnimations() {
+    public void testZeroAnimations() throws Exception {
         mController.goodToGo(TRANSIT_OLD_NONE);
-        verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
+        verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
+        verify(mMockRunner).onAnimationCancelled();
     }
 
     @Test
-    public void testNotReallyStarted() {
+    public void testNotReallyStarted() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
         mController.createRemoteAnimationRecord(win.mActivityRecord,
                 new Point(50, 100), null, new Rect(50, 100, 150, 150), null);
         mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
-        verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
+        verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
+        verify(mMockRunner).onAnimationCancelled();
     }
 
     @Test
@@ -250,7 +254,7 @@
     }
 
     @Test
-    public void testRemovedBeforeStarted() {
+    public void testRemovedBeforeStarted() throws Exception {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
         final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
                 new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
@@ -258,7 +262,8 @@
                 mFinishedCallback);
         win.mActivityRecord.removeImmediately();
         mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
-        verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
+        verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
+        verify(mMockRunner).onAnimationCancelled();
         verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
                 eq(adapter));
     }