Fix flicker with remote animations

There was a race condition where we notified the controlling app
already about transition start, which itself started the animation
and applied the transform of the first frame. However, a little
bit later, we applied the pending transaction from window manager,
which overrode the properties again, leading to a flicker.

Test: go/wm-smoke
Test: Press home button, observe never a flicker
Bug: Surprisingly there isn't one yet.
Change-Id: I849a1573e6fd0487b9b5c22c7a7525bc818661cc
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 9251993..5bc739e 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -96,13 +96,17 @@
         // Scale the timeout with the animator scale the controlling app is using.
         mHandler.postDelayed(mTimeoutRunnable,
                 (long) (TIMEOUT_MS * mService.getCurrentAnimatorScale()));
-        try {
-            mRemoteAnimationAdapter.getRunner().onAnimationStart(createAnimations(),
-                    mFinishedCallback);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to start remote animation", e);
-            onAnimationFinished();
-        }
+
+        final RemoteAnimationTarget[] animations = createAnimations();
+        mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
+            try {
+                mRemoteAnimationAdapter.getRunner().onAnimationStart(animations,
+                        mFinishedCallback);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to start remote animation", e);
+                onAnimationFinished();
+            }
+        });
     }
 
     private RemoteAnimationTarget[] createAnimations() {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 68c8995..4b7cea7 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -599,6 +599,8 @@
                     "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
         }
 
+        mService.mAnimator.executeAfterPrepareSurfacesRunnables();
+
         final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
 
         // If we are ready to perform an app transition, check through all of the app tokens to be
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index cec13ab..b0d42f2 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -92,6 +92,7 @@
      * executed and the corresponding transaction is closed and applied.
      */
     private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();
+    private boolean mInExecuteAfterPrepareSurfacesRunnables;
 
     WindowAnimator(final WindowManagerService service) {
         mService = service;
@@ -438,7 +439,13 @@
         scheduleAnimation();
     }
 
-    private void executeAfterPrepareSurfacesRunnables() {
+    void executeAfterPrepareSurfacesRunnables() {
+
+        // Don't even think about to start recursing!
+        if (mInExecuteAfterPrepareSurfacesRunnables) {
+            return;
+        }
+        mInExecuteAfterPrepareSurfacesRunnables = true;
 
         // Traverse in order they were added.
         final int size = mAfterPrepareSurfacesRunnables.size();
@@ -446,5 +453,6 @@
             mAfterPrepareSurfacesRunnables.get(i).run();
         }
         mAfterPrepareSurfacesRunnables.clear();
+        mInExecuteAfterPrepareSurfacesRunnables = false;
     }
 }