Tighten up pending animations list.

- When we can't start an animation for a task, preemptively remove the
  task from the animation list so that it does not erroneously report as
  animating, or inherit the affect-sysui-flags behaviour.

Bug: 77223419
Test: atest FrameworksServicesTests:com.android.server.wm.RecentsAnimationControllerTest
Change-Id: I5cbc9e68d182cecacf10932a3220039dda5ebeed
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index e8f4545..318b3d2 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -51,6 +51,7 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.google.android.collect.Sets;
 
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
@@ -290,8 +291,10 @@
         mService.mWindowPlacerLocked.performSurfacePlacement();
     }
 
-    private void addAnimation(Task task, boolean isRecentTaskInvisible) {
+    @VisibleForTesting
+    AnimationAdapter addAnimation(Task task, boolean isRecentTaskInvisible) {
         if (DEBUG) Log.d(TAG, "addAnimation(" + task.getName() + ")");
+        // TODO: Refactor this to use the task's animator
         final SurfaceAnimator anim = new SurfaceAnimator(task, null /* animationFinishedCallback */,
                 mService);
         final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task,
@@ -299,6 +302,15 @@
         anim.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */);
         task.commitPendingTransaction();
         mPendingAnimations.add(taskAdapter);
+        return taskAdapter;
+    }
+
+    @VisibleForTesting
+    void removeAnimation(TaskAnimationAdapter taskAdapter) {
+        if (DEBUG) Log.d(TAG, "removeAnimation(" + taskAdapter.mTask.getName() + ")");
+        taskAdapter.mTask.setCanAffectSystemUiFlags(true);
+        taskAdapter.mCapturedFinishCallback.onAnimationFinished(taskAdapter);
+        mPendingAnimations.remove(taskAdapter);
     }
 
     void startAnimation() {
@@ -311,12 +323,21 @@
         try {
             final ArrayList<RemoteAnimationTarget> appAnimations = new ArrayList<>();
             for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
-                final RemoteAnimationTarget target =
-                        mPendingAnimations.get(i).createRemoteAnimationApp();
+                final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
+                final RemoteAnimationTarget target = taskAdapter.createRemoteAnimationApp();
                 if (target != null) {
                     appAnimations.add(target);
+                } else {
+                    removeAnimation(taskAdapter);
                 }
             }
+
+            // Skip the animation if there is nothing to animate
+            if (appAnimations.isEmpty()) {
+                cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
+                return;
+            }
+
             final RemoteAnimationTarget[] appTargets = appAnimations.toArray(
                     new RemoteAnimationTarget[appAnimations.size()]);
             mPendingStart = false;
@@ -365,14 +386,12 @@
         if (DEBUG) Log.d(TAG, "cleanupAnimation(): mPendingAnimations="
                 + mPendingAnimations.size());
         for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
-            final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
-            adapter.mTask.setCanAffectSystemUiFlags(true);
+            final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
             if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
-                adapter.mTask.dontAnimateDimExit();
+                taskAdapter.mTask.dontAnimateDimExit();
             }
-            adapter.mCapturedFinishCallback.onAnimationFinished(adapter);
+            removeAnimation(taskAdapter);
         }
-        mPendingAnimations.clear();
 
         mRunner.asBinder().unlinkToDeath(this, 0);
         // Clear associated input consumers
@@ -457,7 +476,8 @@
         return false;
     }
 
-    private class TaskAnimationAdapter implements AnimationAdapter {
+    @VisibleForTesting
+    class TaskAnimationAdapter implements AnimationAdapter {
 
         private final Task mTask;
         private SurfaceControl mCapturedLeash;