diff options
author | 2024-02-05 21:21:24 +0800 | |
---|---|---|
committer | 2024-09-02 15:53:06 +0800 | |
commit | 267c6c21b7edbd8be27c9946a3fc1a2c2f36fba6 (patch) | |
tree | 3f2ce3a1143fd09b6e165aa911d70ec48ffb9bb8 | |
parent | 424524287184201e8951ee4079ed4faec7502db1 (diff) |
Re-land: Execute afterPrepareSurfacesRunnables after committing...
... the transaction
Some of the runnables will assume the transcation has been committed by
the surface flinger before getting run. For example, the leashes of
insets need to be setup before dispatching to the client. If the order
is not ensured, the transaction sent from the client might be executed
earlier than the one sent from system server which might override the
state of the leash unexpectedly.
This CL executes the runnables when the transaction has been committed.
Fix: 298018626
Fix: 356783416
Flag: EXEMPT bugfix
Test: InsetsPolicyTest InsetsStateControllerTest
ImeInsetsSourceProviderTest CtsWindowManagerDeviceInsets
InputMethodStatsTest KeyboardVisibilityControlTest
MultiDisplayImeTests
Change-Id: I0ee18b75a657eba658561f6f4ace07c59bec64ae
10 files changed, 112 insertions, 64 deletions
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index b66b8bc2115b..9faf1068f27d 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -556,11 +556,37 @@ class InsetsSourceProvider { } mControl = new InsetsSourceControl(mSource.getId(), mSource.getType(), leash, initiallyVisible, surfacePosition, getInsetsHint()); + mStateController.notifySurfaceTransactionReady(this, getSurfaceTransactionId(leash), true); ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "InsetsSource Control %s for target %s", mControl, mControlTarget); } + private long getSurfaceTransactionId(SurfaceControl leash) { + // Here returns mNativeObject (long) as the ID instead of the leash itself so that + // InsetsStateController won't keep referencing the leash unexpectedly. + return leash != null ? leash.mNativeObject : 0; + } + + /** + * This is called when the surface transaction of the leash initialization has been committed. + * + * @param id Indicates which transaction is committed so that stale callbacks can be dropped. + */ + void onSurfaceTransactionCommitted(long id) { + if (mIsLeashReadyForDispatching) { + return; + } + if (mControl == null) { + return; + } + if (id != getSurfaceTransactionId(mControl.getLeash())) { + return; + } + mIsLeashReadyForDispatching = true; + mStateController.notifySurfaceTransactionReady(this, 0, false); + } + void startSeamlessRotation() { if (!mSeamlessRotating) { mSeamlessRotating = true; @@ -582,10 +608,6 @@ class InsetsSourceProvider { return true; } - void onSurfaceTransactionApplied() { - mIsLeashReadyForDispatching = true; - } - void setClientVisible(boolean clientVisible) { if (mClientVisible == clientVisible) { return; @@ -799,6 +821,7 @@ class InsetsSourceProvider { public void onAnimationCancelled(SurfaceControl animationLeash) { if (mAdapter == this) { mStateController.notifyControlRevoked(mControlTarget, InsetsSourceProvider.this); + mStateController.notifySurfaceTransactionReady(InsetsSourceProvider.this, 0, false); mControl = null; mControlTarget = null; mAdapter = null; diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index 098a691e0490..7294e3f12560 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -34,6 +34,7 @@ import android.os.Trace; import android.util.ArrayMap; import android.util.ArraySet; import android.util.SparseArray; +import android.util.SparseLongArray; import android.util.proto.ProtoOutputStream; import android.view.InsetsSource; import android.view.InsetsSourceControl; @@ -59,6 +60,7 @@ class InsetsStateController { private final DisplayContent mDisplayContent; private final SparseArray<InsetsSourceProvider> mProviders = new SparseArray<>(); + private final SparseLongArray mSurfaceTransactionIds = new SparseLongArray(); private final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>> mControlTargetProvidersMap = new ArrayMap<>(); private final SparseArray<InsetsControlTarget> mIdControlTargetMap = new SparseArray<>(); @@ -376,14 +378,32 @@ class InsetsStateController { } } + void notifySurfaceTransactionReady(InsetsSourceProvider provider, long id, boolean ready) { + if (ready) { + mSurfaceTransactionIds.put(provider.getSource().getId(), id); + } else { + mSurfaceTransactionIds.delete(provider.getSource().getId()); + } + } + private void notifyPendingInsetsControlChanged() { if (mPendingControlChanged.isEmpty()) { return; } + final int size = mSurfaceTransactionIds.size(); + final SparseLongArray surfaceTransactionIds = new SparseLongArray(size); + for (int i = 0; i < size; i++) { + surfaceTransactionIds.append( + mSurfaceTransactionIds.keyAt(i), mSurfaceTransactionIds.valueAt(i)); + } mDisplayContent.mWmService.mAnimator.addAfterPrepareSurfacesRunnable(() -> { - for (int i = mProviders.size() - 1; i >= 0; i--) { - final InsetsSourceProvider provider = mProviders.valueAt(i); - provider.onSurfaceTransactionApplied(); + for (int i = 0; i < size; i++) { + final int sourceId = surfaceTransactionIds.keyAt(i); + final InsetsSourceProvider provider = mProviders.get(sourceId); + if (provider == null) { + continue; + } + provider.onSurfaceTransactionCommitted(surfaceTransactionIds.valueAt(i)); } final ArraySet<InsetsControlTarget> newControlTargets = new ArraySet<>(); int displayId = mDisplayContent.getDisplayId(); diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 13334a5f29b1..2342de3676de 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -27,6 +27,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.content.Context; +import android.os.HandlerExecutor; import android.os.Trace; import android.util.Slog; import android.util.TimeUtils; @@ -68,6 +69,8 @@ public class WindowAnimator { private Choreographer mChoreographer; + private final HandlerExecutor mExecutor; + /** * Indicates whether we have an animation frame callback scheduled, which will happen at * vsync-app and then schedule the animation tick at the right time (vsync-sf). @@ -79,8 +82,7 @@ public class WindowAnimator { * A list of runnable that need to be run after {@link WindowContainer#prepareSurfaces} is * executed and the corresponding transaction is closed and applied. */ - private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>(); - private boolean mInExecuteAfterPrepareSurfacesRunnables; + private ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>(); private final SurfaceControl.Transaction mTransaction; @@ -91,6 +93,7 @@ public class WindowAnimator { mTransaction = service.mTransactionFactory.get(); service.mAnimationHandler.runWithScissors( () -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */); + mExecutor = new HandlerExecutor(service.mAnimationHandler); mAnimationFrameCallback = frameTimeNs -> { synchronized (mService.mGlobalLock) { @@ -198,6 +201,19 @@ public class WindowAnimator { updateRunningExpensiveAnimationsLegacy(); } + final ArrayList<Runnable> afterPrepareSurfacesRunnables = mAfterPrepareSurfacesRunnables; + if (!afterPrepareSurfacesRunnables.isEmpty()) { + mAfterPrepareSurfacesRunnables = new ArrayList<>(); + mTransaction.addTransactionCommittedListener(mExecutor, () -> { + synchronized (mService.mGlobalLock) { + // Traverse in order they were added. + for (int i = 0, size = afterPrepareSurfacesRunnables.size(); i < size; i++) { + afterPrepareSurfacesRunnables.get(i).run(); + } + afterPrepareSurfacesRunnables.clear(); + } + }); + } Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "applyTransaction"); mTransaction.apply(); Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); @@ -205,7 +221,6 @@ public class WindowAnimator { ProtoLog.i(WM_SHOW_TRANSACTIONS, "<<< CLOSE TRANSACTION animate"); mService.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); - executeAfterPrepareSurfacesRunnables(); if (DEBUG_WINDOW_TRACE) { Slog.i(TAG, "!!! animate: exit" @@ -287,34 +302,10 @@ public class WindowAnimator { /** * Adds a runnable to be executed after {@link WindowContainer#prepareSurfaces} is called and - * the corresponding transaction is closed and applied. + * the corresponding transaction is closed, applied, and committed. */ void addAfterPrepareSurfacesRunnable(Runnable r) { - // If runnables are already being handled in executeAfterPrepareSurfacesRunnable, then just - // immediately execute the runnable passed in. - if (mInExecuteAfterPrepareSurfacesRunnables) { - r.run(); - return; - } - mAfterPrepareSurfacesRunnables.add(r); scheduleAnimation(); } - - 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(); - for (int i = 0; i < size; i++) { - mAfterPrepareSurfacesRunnables.get(i).run(); - } - mAfterPrepareSurfacesRunnables.clear(); - mInExecuteAfterPrepareSurfacesRunnables = false; - } } diff --git a/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java b/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java index e27bb4c8c3b6..b9ece9360980 100644 --- a/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java +++ b/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java @@ -40,12 +40,19 @@ import java.util.concurrent.Executor; public class StubTransaction extends SurfaceControl.Transaction { private HashSet<Runnable> mWindowInfosReportedListeners = new HashSet<>(); + private HashSet<SurfaceControl.TransactionCommittedListener> mTransactionCommittedListeners = + new HashSet<>(); @Override public void apply() { for (Runnable listener : mWindowInfosReportedListeners) { listener.run(); } + for (SurfaceControl.TransactionCommittedListener listener + : mTransactionCommittedListeners) { + listener.onTransactionCommitted(); + } + mTransactionCommittedListeners.clear(); } @Override @@ -239,6 +246,9 @@ public class StubTransaction extends SurfaceControl.Transaction { @Override public SurfaceControl.Transaction addTransactionCommittedListener(Executor executor, SurfaceControl.TransactionCommittedListener listener) { + SurfaceControl.TransactionCommittedListener listenerInner = + () -> executor.execute(listener::onTransactionCommitted); + mTransactionCommittedListeners.add(listenerInner); return this; } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java index 0c1fbf3cb3d7..c294bc62c7ac 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java @@ -94,6 +94,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { public void setUp() throws Exception { assumeFalse(WindowManagerService.sEnableShellTransitions); mAppTransitionController = new AppTransitionController(mWm, mDisplayContent); + mWm.mAnimator.ready(); } @Test @@ -855,7 +856,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // Animation run by the remote handler. assertTrue(remoteAnimationRunner.isAnimationStarted()); @@ -886,7 +887,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(openingActivity, closingActivity, null /* changingTaskFragment */); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // Animation is not run by the remote handler because the activity is filling the Task. assertFalse(remoteAnimationRunner.isAnimationStarted()); @@ -921,7 +922,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(openingActivity, closingActivity, null /* changingTaskFragment */); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // Animation run by the remote handler. assertTrue(remoteAnimationRunner.isAnimationStarted()); @@ -946,7 +947,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // Animation run by the remote handler. assertTrue(remoteAnimationRunner.isAnimationStarted()); @@ -973,7 +974,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment1); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // Animation run by the remote handler. assertTrue(remoteAnimationRunner.isAnimationStarted()); @@ -997,7 +998,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // Animation not run by the remote handler. assertFalse(remoteAnimationRunner.isAnimationStarted()); @@ -1024,7 +1025,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // Animation should not run by the remote handler when there are non-embedded activities of // different UID. @@ -1051,7 +1052,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // Animation should not run by the remote handler when there is wallpaper in the transition. assertFalse(remoteAnimationRunner.isAnimationStarted()); @@ -1085,7 +1086,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(activity1, null /* closingActivity */, taskFragment); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // The animation will be animated remotely by client and all activities are input disabled // for untrusted animation. @@ -1136,7 +1137,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // The animation will be animated remotely by client and all activities are input disabled // for untrusted animation. @@ -1178,7 +1179,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { // Prepare and start transition. prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); // The animation will be animated remotely by client, but input should not be dropped for // fully trusted. @@ -1302,4 +1303,4 @@ public class AppTransitionControllerTest extends WindowTestsBase { doReturn(mock(RemoteAnimationTarget.class)).when(activity).createRemoteAnimationTarget( any()); } -}
\ No newline at end of file +} diff --git a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java index ea175a5a52b0..f70dcebce30d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java @@ -51,6 +51,7 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase { public void setUp() throws Exception { mImeProvider = mDisplayContent.getInsetsStateController().getImeSourceProvider(); mImeProvider.getSource().setVisible(true); + mWm.mAnimator.ready(); } @Test @@ -151,8 +152,8 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase { assertFalse(mImeProvider.isScheduledAndReadyToShowIme()); assertFalse(mImeProvider.isImeShowing()); - // Starting the afterPrepareSurfacesRunnable picks up the show scheduled above. - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + // Waiting for the afterPrepareSurfacesRunnable picks up the show scheduled above. + waitUntilWindowAnimatorIdle(); // No longer scheduled as it was already shown. assertFalse(mImeProvider.isScheduledAndReadyToShowIme()); assertTrue(mImeProvider.isImeShowing()); diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java index 619080770f1e..e8d089c61362 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java @@ -187,8 +187,8 @@ public class InsetsSourceProviderTest extends WindowTestsBase { assertEquals(mProvider.getControlTarget(), target); assertNull(mProvider.getLeash(target)); - // After surface transactions are applied, the leash is ready for dispatching. - mProvider.onSurfaceTransactionApplied(); + // Set the leash to be ready for dispatching. + mProvider.mIsLeashReadyForDispatching = true; assertNotNull(mProvider.getLeash(target)); // We do have fake control for the fake control target, but that has no leash. diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index 964264d82b65..d0d7c06bd706 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -388,6 +388,7 @@ public class InsetsStateControllerTest extends WindowTestsBase { mDisplayContent.getInsetsPolicy().updateBarControlTarget(app); mDisplayContent.getInsetsPolicy().showTransient(statusBars(), true /* isGestureOnSystemBar */); + mWm.mAnimator.ready(); waitUntilWindowAnimatorIdle(); assertTrue(mDisplayContent.getInsetsPolicy().isTransient(statusBars())); 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 6f7d0dced484..c5cbedb9193c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java @@ -110,6 +110,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { runWithScissors(mWm.mH, () -> mHandler = new TestHandler(null, mClock), 0); mController = new RemoteAnimationController(mWm, mDisplayContent, mAdapter, mHandler, false /*isActivityEmbedding*/); + mWm.mAnimator.ready(); } private WindowState createAppOverlayWindow() { @@ -133,7 +134,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, mFinishedCallback); mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor = @@ -165,7 +166,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, mFinishedCallback); mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor = @@ -287,7 +288,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, mFinishedCallback); mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor = @@ -333,7 +334,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { task.applyAnimationUnchecked(null /* lp */, true /* enter */, TRANSIT_OLD_TASK_OPEN, false /* isVoiceInteraction */, null /* sources */); mController.goodToGo(TRANSIT_OLD_TASK_OPEN); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); try { @@ -360,7 +361,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback); mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor = @@ -414,7 +415,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback); mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor = @@ -468,7 +469,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback); mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor = @@ -523,7 +524,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, mFinishedCallback); mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor = @@ -556,7 +557,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, mFinishedCallback); mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor = @@ -592,7 +593,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, mFinishedCallback); mController.goodToGo(TRANSIT_OLD_KEYGUARD_GOING_AWAY); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor = @@ -642,7 +643,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, mFinishedCallback); mController.goodToGo(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor = ArgumentCaptor.forClass(RemoteAnimationTarget[].class); final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor = @@ -742,7 +743,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, mFinishedCallback); mController.goodToGo(transit); - mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + waitUntilWindowAnimatorIdle(); return adapter; } diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index 1e39f0b963b7..de3c1313b0ee 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -571,7 +571,7 @@ public class SystemServicesTestRule implements TestRule { // This makes sure all previous messages in the handler are fully processed vs. just popping // them from the message queue. final AtomicBoolean currentMessagesProcessed = new AtomicBoolean(false); - wm.mAnimator.getChoreographer().postFrameCallback(time -> { + wm.mAnimator.addAfterPrepareSurfacesRunnable(() -> { synchronized (currentMessagesProcessed) { currentMessagesProcessed.set(true); currentMessagesProcessed.notifyAll(); |