diff options
| author | 2018-01-05 18:28:36 +0100 | |
|---|---|---|
| committer | 2018-01-08 15:44:40 +0100 | |
| commit | d6d971695647e742e24986be396524e8528d2f29 (patch) | |
| tree | eccf4704f524437068205819ad4613d0cc6ed4c7 | |
| parent | 8fb00b2c28eba84c88aa14d803c1a4687ec00fa6 (diff) | |
Make sure app transition are started simultaneously
Test: go/wm-smoke
Test: Lock device in split screen, make sure everything is
absolutely synchronized when unlocking
Bug: 64674361
Change-Id: I25352d7a6b8beb9729310dd525710dca20a78166
3 files changed, 69 insertions, 17 deletions
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java index 3a41eb0e2afc..dc62cc89c14d 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java @@ -67,6 +67,9 @@ class SurfaceAnimationRunner { @VisibleForTesting final ArrayMap<SurfaceControl, RunningAnimation> mRunningAnimations = new ArrayMap<>(); + @GuardedBy("mLock") + private boolean mAnimationStartDeferred; + SurfaceAnimationRunner() { this(null /* callbackProvider */, null /* animatorFactory */, new Transaction()); } @@ -86,13 +89,41 @@ class SurfaceAnimationRunner { : SfValueAnimator::new; } + /** + * Defers starting of animations until {@link #continueStartingAnimations} is called. This + * method is NOT nestable. + * + * @see #continueStartingAnimations + */ + void deferStartingAnimations() { + synchronized (mLock) { + mAnimationStartDeferred = true; + } + } + + /** + * Continues starting of animations. + * + * @see #deferStartingAnimations + */ + void continueStartingAnimations() { + synchronized (mLock) { + mAnimationStartDeferred = false; + if (!mPendingAnimations.isEmpty()) { + mChoreographer.postFrameCallback(this::startAnimations); + } + } + } + void startAnimation(AnimationSpec a, SurfaceControl animationLeash, Transaction t, Runnable finishCallback) { synchronized (mLock) { final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash, finishCallback); mPendingAnimations.put(animationLeash, runningAnim); - mChoreographer.postFrameCallback(this::stepAnimation); + if (!mAnimationStartDeferred) { + mChoreographer.postFrameCallback(this::startAnimations); + } // Some animations (e.g. move animations) require the initial transform to be applied // immediately. @@ -185,7 +216,7 @@ class SurfaceAnimationRunner { a.mAnimSpec.apply(t, a.mLeash, currentPlayTime); } - private void stepAnimation(long frameTimeNanos) { + private void startAnimations(long frameTimeNanos) { synchronized (mLock) { startPendingAnimationsLocked(); } diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index bdab9c765d36..08f49f689323 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -349,21 +349,28 @@ class WindowSurfacePlacer { animLp = null; } - processApplicationsAnimatingInPlace(transit); - - mTmpLayerAndToken.token = null; - handleClosingApps(transit, animLp, voiceInteraction, mTmpLayerAndToken); - final AppWindowToken topClosingApp = mTmpLayerAndToken.token; - final AppWindowToken topOpeningApp = handleOpeningApps(transit, animLp, voiceInteraction); - - mService.mAppTransition.setLastAppTransition(transit, topOpeningApp, topClosingApp); - - final int flags = mService.mAppTransition.getTransitFlags(); - int layoutRedo = mService.mAppTransition.goodToGo(transit, topOpeningApp, - topClosingApp, mService.mOpeningApps, mService.mClosingApps); - handleNonAppWindowsInTransition(transit, flags); - mService.mAppTransition.postAnimationCallback(); - mService.mAppTransition.clear(); + final int layoutRedo; + mService.mSurfaceAnimationRunner.deferStartingAnimations(); + try { + processApplicationsAnimatingInPlace(transit); + + mTmpLayerAndToken.token = null; + handleClosingApps(transit, animLp, voiceInteraction, mTmpLayerAndToken); + final AppWindowToken topClosingApp = mTmpLayerAndToken.token; + final AppWindowToken topOpeningApp = handleOpeningApps(transit, animLp, + voiceInteraction); + + mService.mAppTransition.setLastAppTransition(transit, topOpeningApp, topClosingApp); + + final int flags = mService.mAppTransition.getTransitFlags(); + layoutRedo = mService.mAppTransition.goodToGo(transit, topOpeningApp, + topClosingApp, mService.mOpeningApps, mService.mClosingApps); + handleNonAppWindowsInTransition(transit, flags); + mService.mAppTransition.postAnimationCallback(); + mService.mAppTransition.clear(); + } finally { + mService.mSurfaceAnimationRunner.continueStartingAnimations(); + } mService.mTaskSnapshotController.onTransitionStarting(); diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java index 17fe6427f756..4831fcd67314 100644 --- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java +++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java @@ -162,6 +162,20 @@ public class SurfaceAnimationRunnerTest extends WindowTestsBase { verify(mMockAnimationSpec, atLeastOnce()).apply(any(), any(), eq(0L)); } + @Test + public void testDeferStartingAnimations() throws Exception { + mSurfaceAnimationRunner.deferStartingAnimations(); + mSurfaceAnimationRunner.startAnimation(createTranslateAnimation(), mMockSurface, + mMockTransaction, this::finishedCallback); + waitUntilNextFrame(); + assertTrue(mSurfaceAnimationRunner.mRunningAnimations.isEmpty()); + mSurfaceAnimationRunner.continueStartingAnimations(); + waitUntilNextFrame(); + assertFalse(mSurfaceAnimationRunner.mRunningAnimations.isEmpty()); + mFinishCallbackLatch.await(1, SECONDS); + assertFinishCallbackCalled(); + } + private void waitUntilNextFrame() throws Exception { final CountDownLatch latch = new CountDownLatch(1); mSurfaceAnimationRunner.mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, |