Use destroy in transaction for animation

Previously, the code calls destroy which will be invoked immediately so there
needed to be ways to delay destroy. This caused some overhead where there
needed to be Runnables to ensure client state updates were called before the
destroy. Instead, use the Transaction.destroy so the destroy doesn't get invoked
until apply is called. This allows any other client states to get updated before
the destroy is called.

This is specifically necessary for reparent calls since a Surface can be
reparented from a Surface that's about to get destroyed to a valid Surface
that's not getting destroyed. This change ensures that Surfaces will get
reparented before Surfaces are destroyed when Transactions are applied.

Original CL: ag/3573288
Reason for revert: Original issue is fixed in ag/3647191.

Fixes: 72953020
Test: SurfaceAnimatorTest
Change-Id: I8bc58e0efc2ae1558c122a40eb52e9c874c0c997
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index bd7f8e5..fc78211 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -152,6 +152,7 @@
     private static native void nativeSeverChildren(long transactionObj, long nativeObject);
     private static native void nativeSetOverrideScalingMode(long transactionObj, long nativeObject,
             int scalingMode);
+    private static native void nativeDestroy(long transactionObj, long nativeObject);
     private static native IBinder nativeGetHandle(long nativeObject);
     private static native boolean nativeGetTransformToDisplayInverse(long nativeObject);
 
@@ -1570,6 +1571,16 @@
             return this;
         }
 
+        /**
+         * Same as {@link #destroy()} except this is invoked in a transaction instead of
+         * immediately.
+         */
+        public Transaction destroy(SurfaceControl sc) {
+            sc.checkNotReleased();
+            nativeDestroy(mNativeObject, sc.mNativeObject);
+            return this;
+        }
+
         public Transaction setDisplaySurface(IBinder displayToken, Surface surface) {
             if (displayToken == null) {
                 throw new IllegalArgumentException("displayToken must not be null");
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 0ef5445..8ca5062 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -846,6 +846,14 @@
     transaction->setOverrideScalingMode(ctrl, scalingMode);
 }
 
+static void nativeDestroyInTransaction(JNIEnv* env, jclass clazz,
+                                       jlong transactionObj,
+                                       jlong nativeObject) {
+    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+    auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+    transaction->destroySurface(ctrl);
+}
+
 static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
     auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
     return javaObjectForIBinder(env, ctrl->getHandle());
@@ -997,6 +1005,8 @@
             (void*)nativeSeverChildren } ,
     {"nativeSetOverrideScalingMode", "(JJI)V",
             (void*)nativeSetOverrideScalingMode },
+    {"nativeDestroy", "(JJ)V",
+            (void*)nativeDestroyInTransaction },
     {"nativeGetHandle", "(J)Landroid/os/IBinder;",
             (void*)nativeGetHandle },
     {"nativeScreenshotToBuffer",
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index db95634..3cd3e8b 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -53,8 +53,7 @@
 
     AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader) {
         mAppToken = appToken;
-        mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished,
-                appToken.mService.mAnimator::addAfterPrepareSurfacesRunnable, appToken.mService);
+        mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, appToken.mService);
         mWidth = thumbnailHeader.getWidth();
         mHeight = thumbnailHeader.getHeight();
 
@@ -145,11 +144,6 @@
     }
 
     @Override
-    public void destroyAfterPendingTransaction(SurfaceControl surface) {
-        mAppToken.destroyAfterPendingTransaction(surface);
-    }
-
-    @Override
     public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
         t.setLayer(leash, Integer.MAX_VALUE);
     }
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 4394a99..a180a3a 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -55,11 +55,6 @@
         }
 
         @Override
-        public void destroyAfterPendingTransaction(SurfaceControl surface) {
-            mHost.destroyAfterPendingTransaction(surface);
-        }
-
-        @Override
         public SurfaceControl.Builder makeAnimationLeash() {
             return mHost.makeAnimationLeash();
         }
@@ -119,7 +114,7 @@
                 if (!mDimming) {
                     mDimLayer.destroy();
                 }
-            }, mHost.mService.mAnimator::addAfterPrepareSurfacesRunnable, mHost.mService);
+            }, mHost.mService);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 13357b8..16228d7 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -382,11 +382,6 @@
      */
     private int mSurfaceSize;
 
-    /**
-     * A list of surfaces to be destroyed after {@link #mPendingTransaction} is applied.
-     */
-    private final ArrayList<SurfaceControl> mPendingDestroyingSurfaces = new ArrayList<>();
-
     /** Temporary float array to retrieve 3x3 matrix values. */
     private final float[] mTmpFloats = new float[9];
 
@@ -1954,10 +1949,6 @@
                 }
             }
             mService.mAnimator.removeDisplayLocked(mDisplayId);
-
-            // The pending transaction won't be applied so we should
-            // just clean up any surfaces pending destruction.
-            onPendingTransactionApplied();
         } finally {
             mRemovingDisplay = false;
         }
@@ -3874,22 +3865,6 @@
     }
 
     @Override
-    public void destroyAfterPendingTransaction(SurfaceControl surface) {
-        mPendingDestroyingSurfaces.add(surface);
-    }
-
-    /**
-     * Destroys any surfaces that have been put into the pending list with
-     * {@link #destroyAfterPendingTransaction}.
-     */
-    void onPendingTransactionApplied() {
-        for (int i = mPendingDestroyingSurfaces.size() - 1; i >= 0; i--) {
-            mPendingDestroyingSurfaces.get(i).destroy();
-        }
-        mPendingDestroyingSurfaces.clear();
-    }
-
-    @Override
     void prepareSurfaces() {
         final ScreenRotationAnimation screenRotationAnimation =
                 mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
@@ -3903,6 +3878,7 @@
             mPendingTransaction.setAlpha(mWindowingLayer,
                     screenRotationAnimation.getEnterTransformation().getAlpha());
         }
+
         super.prepareSurfaces();
     }
 
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 31b5c69..579062f 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -219,7 +219,7 @@
     private void addAnimation(Task task) {
         if (DEBUG) Log.d(TAG, "addAnimation(" + task.getName() + ")");
         final SurfaceAnimator anim = new SurfaceAnimator(task, null /* animationFinishedCallback */,
-                mService.mAnimator::addAfterPrepareSurfacesRunnable, mService);
+                mService);
         final TaskAnimationAdapter taskAdapter = new TaskAnimationAdapter(task);
         anim.startAnimation(task.getPendingTransaction(), taskAdapter, false /* hidden */);
         task.commitPendingTransaction();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 6356a35..9e9d8b6 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -814,7 +814,6 @@
         mService.enableScreenIfNeededLocked();
 
         mService.scheduleAnimationLocked();
-        mService.mWindowPlacerLocked.destroyPendingSurfaces();
 
         if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
                 "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 83baee1..76f5396 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -33,7 +33,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.PrintWriter;
-import java.util.function.Consumer;
 
 /**
  * A class that can run animations on objects that have a set of child surfaces. We do this by
@@ -60,21 +59,17 @@
     /**
      * @param animatable The object to animate.
      * @param animationFinishedCallback Callback to invoke when an animation has finished running.
-     * @param addAfterPrepareSurfaces Consumer that takes a runnable and executes it after preparing
-     *                                surfaces in WM. Can be implemented differently during testing.
      */
     SurfaceAnimator(Animatable animatable, @Nullable Runnable animationFinishedCallback,
-            Consumer<Runnable> addAfterPrepareSurfaces, WindowManagerService service) {
+            WindowManagerService service) {
         mAnimatable = animatable;
         mService = service;
         mAnimationFinishedCallback = animationFinishedCallback;
-        mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback,
-                addAfterPrepareSurfaces);
+        mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback);
     }
 
     private OnAnimationFinishedCallback getFinishedCallback(
-            @Nullable Runnable animationFinishedCallback,
-            Consumer<Runnable> addAfterPrepareSurfaces) {
+            @Nullable Runnable animationFinishedCallback) {
         return anim -> {
             synchronized (mService.mWindowMap) {
                 final SurfaceAnimator target = mService.mAnimationTransferMap.remove(anim);
@@ -83,30 +78,13 @@
                     return;
                 }
 
-                // TODO: This should use pendingTransaction eventually, but right now things
-                // happening on the animation finished callback are happening on the global
-                // transaction.
-                // For now we need to run this after it's guaranteed that the transaction that
-                // reparents the surface onto the leash is executed already. Otherwise this may be
-                // executed first, leading to surface loss, as the reparent operations wouldn't
-                // be in order.
-                addAfterPrepareSurfaces.accept(() -> {
-                    if (anim != mAnimation) {
-                        // Callback was from another animation - ignore.
-                        return;
-                    }
-                    final Transaction t = new Transaction();
-                    SurfaceControl.openTransaction();
-                    try {
-                        reset(t, true /* destroyLeash */);
-                        if (animationFinishedCallback != null) {
-                            animationFinishedCallback.run();
-                        }
-                    } finally {
-                        SurfaceControl.mergeToGlobalTransaction(t);
-                        SurfaceControl.closeTransaction();
-                    }
-                });
+                if (anim != mAnimation) {
+                    return;
+                }
+                reset(mAnimatable.getPendingTransaction(), true /* destroyLeash */);
+                if (animationFinishedCallback != null) {
+                    animationFinishedCallback.run();
+                }
             }
         };
     }
@@ -282,15 +260,19 @@
         final SurfaceControl surface = mAnimatable.getSurfaceControl();
         final SurfaceControl parent = mAnimatable.getParentSurfaceControl();
 
+        boolean scheduleAnim = false;
+
         // If the surface was destroyed, we don't care to reparent it back.
         final boolean destroy = mLeash != null && surface != null && parent != null;
         if (destroy) {
             if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to original parent");
             t.reparent(surface, parent.getHandle());
+            scheduleAnim = true;
         }
         mService.mAnimationTransferMap.remove(mAnimation);
         if (mLeash != null && destroyLeash) {
-            mAnimatable.destroyAfterPendingTransaction(mLeash);
+            t.destroy(mLeash);
+            scheduleAnim = true;
         }
         mLeash = null;
         mAnimation = null;
@@ -298,6 +280,11 @@
         // Make sure to inform the animatable after the leash was destroyed.
         if (destroy) {
             mAnimatable.onAnimationLeashDestroyed(t);
+            scheduleAnim = true;
+        }
+
+        if (scheduleAnim) {
+            mService.scheduleAnimationLocked();
         }
     }
 
@@ -379,13 +366,6 @@
         void onAnimationLeashDestroyed(Transaction t);
 
         /**
-         * Destroy a given surface after executing {@link #getPendingTransaction}.
-         *
-         * @see WindowContainer#destroyAfterPendingTransaction
-         */
-        void destroyAfterPendingTransaction(SurfaceControl surface);
-
-        /**
          * @return A new surface to be used for the animation leash, inserted at the correct
          *         position in the hierarchy.
          */
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 20349b9..ab10197 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -226,13 +226,6 @@
                 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION animate");
             }
 
-            final int numDisplays = mDisplayContentsAnimators.size();
-            for (int i = 0; i < numDisplays; i++) {
-                final int displayId = mDisplayContentsAnimators.keyAt(i);
-                final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
-                dc.onPendingTransactionApplied();
-            }
-
             boolean hasPendingLayoutChanges = mService.mRoot.hasPendingLayoutChanges(this);
             boolean doRequest = false;
             if (mBulkUpdateParams != 0) {
@@ -266,7 +259,6 @@
             }
 
             mService.destroyPreservedSurfaceLocked();
-            mService.mWindowPlacerLocked.destroyPendingSurfaces();
 
             executeAfterPrepareSurfacesRunnables();
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 1f7caff..93e9137 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -109,8 +109,7 @@
     WindowContainer(WindowManagerService service) {
         mService = service;
         mPendingTransaction = service.mTransactionFactory.make();
-        mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished,
-                service.mAnimator::addAfterPrepareSurfacesRunnable, service);
+        mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, service);
     }
 
     @Override
@@ -286,8 +285,9 @@
         }
 
         if (mSurfaceControl != null) {
-            destroyAfterPendingTransaction(mSurfaceControl);
+            getPendingTransaction().destroy(mSurfaceControl);
             mSurfaceControl = null;
+            scheduleAnimation();
         }
 
         if (mParent != null) {
@@ -1075,19 +1075,6 @@
         return mSurfaceControl;
     }
 
-    /**
-     * Destroy a given surface after executing mPendingTransaction. This is
-     * largely a workaround for destroy not being part of transactions
-     * rather than an intentional design, so please take care when
-     * expanding use.
-     */
-    @Override
-    public void destroyAfterPendingTransaction(SurfaceControl surface) {
-        if (mParent != null) {
-            mParent.destroyAfterPendingTransaction(surface);
-        }
-    }
-
     @Override
     public Transaction getPendingTransaction() {
         return mPendingTransaction;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b706096..3a81895 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4013,7 +4013,9 @@
 
         final boolean hasSurface = mWinAnimator.hasSurface();
         if (hasSurface) {
-            mWinAnimator.hide("onExitAnimationDone");
+            // Use pendingTransaction here so hide is done the same transaction as the other
+            // animations when exiting
+            mWinAnimator.hide(getPendingTransaction(), "onExitAnimationDone");
         }
 
         // If we have an app token, we ask it to destroy the surface for us, so that it can take
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 9ce0537..eeefcf5 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -164,6 +164,8 @@
 
     private boolean mAnimationStartDelayed;
 
+    private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+
     /** The pixel format of the underlying SurfaceControl */
     int mSurfaceFormat;
 
@@ -280,16 +282,21 @@
         }
     }
 
-    void hide(String reason) {
+    void hide(SurfaceControl.Transaction transaction, String reason) {
         if (!mLastHidden) {
             //dump();
             mLastHidden = true;
             if (mSurfaceController != null) {
-                mSurfaceController.hideInTransaction(reason);
+                mSurfaceController.hide(transaction, reason);
             }
         }
     }
 
+    void hide(String reason) {
+        hide(mTmpTransaction, reason);
+        SurfaceControl.mergeToGlobalTransaction(mTmpTransaction);
+    }
+
     boolean finishDrawingLocked() {
         final boolean startingWindow =
                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 554a600..d88e59c 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -86,6 +86,8 @@
     private final int mWindowType;
     private final Session mWindowSession;
 
+    private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+
     public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
             int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
         mAnimator = animator;
@@ -148,21 +150,23 @@
         }
     }
 
-    void hideInTransaction(String reason) {
+    void hide(SurfaceControl.Transaction transaction, String reason) {
         if (SHOW_TRANSACTIONS) logSurface("HIDE ( " + reason + " )", null);
         mHiddenForOtherReasons = true;
 
         mAnimator.destroyPreservedSurfaceLocked();
-        updateVisibility();
+        if (mSurfaceShown) {
+            hideSurface(transaction);
+        }
     }
 
-    private void hideSurface() {
+    private void hideSurface(SurfaceControl.Transaction transaction) {
         if (mSurfaceControl == null) {
             return;
         }
         setShown(false);
         try {
-            mSurfaceControl.hide();
+            transaction.hide(mSurfaceControl);
         } catch (RuntimeException e) {
             Slog.w(TAG, "Exception hiding surface in " + this);
         }
@@ -421,7 +425,8 @@
     private boolean updateVisibility() {
         if (mHiddenForCrop || mHiddenForOtherReasons) {
             if (mSurfaceShown) {
-                hideSurface();
+                hideSurface(mTmpTransaction);
+                SurfaceControl.mergeToGlobalTransaction(mTmpTransaction);
             }
             return false;
         } else {
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 66c7293..92efcda 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -102,7 +102,6 @@
     }
     private final LayerAndToken mTmpLayerAndToken = new LayerAndToken();
 
-    private final ArrayList<SurfaceControl> mPendingDestroyingSurfaces = new ArrayList<>();
     private final SparseIntArray mTempTransitionReasons = new SparseIntArray();
 
     private final Runnable mPerformSurfacePlacement;
@@ -697,25 +696,6 @@
         }
     }
 
-    /**
-     * Puts the {@param surface} into a pending list to be destroyed after the current transaction
-     * has been committed.
-     */
-    void destroyAfterTransaction(SurfaceControl surface) {
-        mPendingDestroyingSurfaces.add(surface);
-    }
-
-    /**
-     * Destroys any surfaces that have been put into the pending list with
-     * {@link #destroyAfterTransaction}.
-     */
-    void destroyPendingSurfaces() {
-        for (int i = mPendingDestroyingSurfaces.size() - 1; i >= 0; i--) {
-            mPendingDestroyingSurfaces.get(i).destroy();
-        }
-        mPendingDestroyingSurfaces.clear();
-    }
-
     public void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + "mTraversalScheduled=" + mTraversalScheduled);
         pw.println(prefix + "mHoldScreenWindow=" + mService.mRoot.mHoldScreenWindow);
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index b55c79b..79a9610 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -131,7 +131,6 @@
             assertNoStartingWindow(controller.getAppWindowToken(mDisplayContent));
 
             controller.getAppWindowToken(mDisplayContent).getParent().getParent().removeImmediately();
-            mDisplayContent.onPendingTransactionApplied();
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 64c3037..a120eba 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -23,11 +23,11 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.SurfaceControl;
@@ -39,7 +39,6 @@
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -47,7 +46,6 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
-import java.util.concurrent.CountDownLatch;
 
 /**
  * Test class for {@link SurfaceAnimatorTest}.
@@ -87,7 +85,7 @@
         callbackCaptor.getValue().onAnimationFinished(mSpec);
         assertNotAnimating(mAnimatable);
         assertTrue(mAnimatable.mFinishedCallbackCalled);
-        assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash));
+        verify(mTransaction).destroy(eq(mAnimatable.mLeash));
         // TODO: Verify reparenting once we use mPendingTransaction to reparent it back
     }
 
@@ -97,7 +95,7 @@
         final SurfaceControl firstLeash = mAnimatable.mLeash;
         mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec2, true /* hidden */);
 
-        assertTrue(mAnimatable.mPendingDestroySurfaces.contains(firstLeash));
+        verify(mTransaction).destroy(eq(firstLeash));
         assertFalse(mAnimatable.mFinishedCallbackCalled);
 
         final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
@@ -124,7 +122,7 @@
         assertNotAnimating(mAnimatable);
         verify(mSpec).onAnimationCancelled(any());
         assertTrue(mAnimatable.mFinishedCallbackCalled);
-        assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash));
+        verify(mTransaction).destroy(eq(mAnimatable.mLeash));
     }
 
     @Test
@@ -145,7 +143,7 @@
         verifyZeroInteractions(mSpec);
         assertNotAnimating(mAnimatable);
         assertTrue(mAnimatable.mFinishedCallbackCalled);
-        assertTrue(mAnimatable.mPendingDestroySurfaces.contains(mAnimatable.mLeash));
+        verify(mTransaction).destroy(eq(mAnimatable.mLeash));
     }
 
     @Test
@@ -161,11 +159,11 @@
         assertNotAnimating(mAnimatable);
         assertAnimating(mAnimatable2);
         assertEquals(leash, mAnimatable2.mSurfaceAnimator.mLeash);
-        assertFalse(mAnimatable.mPendingDestroySurfaces.contains(leash));
+        verify(mTransaction, never()).destroy(eq(leash));
         callbackCaptor.getValue().onAnimationFinished(mSpec);
         assertNotAnimating(mAnimatable2);
         assertTrue(mAnimatable2.mFinishedCallbackCalled);
-        assertTrue(mAnimatable2.mPendingDestroySurfaces.contains(leash));
+        verify(mTransaction).destroy(eq(leash));
     }
 
     private void assertAnimating(MyAnimatable animatable) {
@@ -182,7 +180,6 @@
 
         final SurfaceControl mParent;
         final SurfaceControl mSurface;
-        final ArrayList<SurfaceControl> mPendingDestroySurfaces = new ArrayList<>();
         final SurfaceAnimator mSurfaceAnimator;
         SurfaceControl mLeash;
         boolean mFinishedCallbackCalled;
@@ -198,7 +195,7 @@
                     .build();
             mFinishedCallbackCalled = false;
             mLeash = null;
-            mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, Runnable::run, sWm);
+            mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, sWm);
         }
 
         @Override
@@ -219,11 +216,6 @@
         }
 
         @Override
-        public void destroyAfterPendingTransaction(SurfaceControl surface) {
-            mPendingDestroySurfaces.add(surface);
-        }
-
-        @Override
         public Builder makeAnimationLeash() {
             return new SurfaceControl.Builder(mSession) {