From 2e3c31d0925ecad47e10c7d215b55afd4714b211 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Mon, 20 Nov 2017 19:49:00 +0100 Subject: [PATCH] Lock free app animations (5/n): Reimplement skip first frame Test: go/wm-smoke Test: Close app, inspect transition with WindowScope, make sure first frame of animation is skipped Bug: Change-Id: I68c135621df47c50696e318c4394da36ce806922 --- .../com/android/server/wm/AppWindowThumbnail.java | 11 +++++++++-- .../java/com/android/server/wm/AppWindowToken.java | 4 +++- .../com/android/server/wm/LocalAnimationAdapter.java | 7 +++++++ .../com/android/server/wm/SurfaceAnimationRunner.java | 5 +++++ .../com/android/server/wm/WindowAnimationSpec.java | 9 ++++++++- .../core/java/com/android/server/wm/WindowState.java | 3 ++- .../android/server/wm/SurfaceAnimationRunnerTest.java | 2 +- 7 files changed, 35 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java index a8bc270d0b586..65abcf5306634 100644 --- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java +++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java @@ -86,8 +86,11 @@ class AppWindowThumbnail implements Animatable { void startAnimation(Transaction t, Animation anim) { anim.restrictDuration(MAX_ANIMATION_DURATION); anim.scaleCurrentDuration(mAppToken.mService.getTransitionAnimationScaleLocked()); - mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(new WindowAnimationSpec(anim, - new Point()), mAppToken.mService.mSurfaceAnimationRunner), + mSurfaceAnimator.startAnimation(t, + new LocalAnimationAdapter( + new WindowAnimationSpec(anim, new Point(), + mAppToken.mService.mAppTransition.canSkipFirstFrame()), + mAppToken.mService.mSurfaceAnimationRunner), false /* hidden */); } @@ -95,6 +98,7 @@ class AppWindowThumbnail implements Animatable { } void setShowing(Transaction pendingTransaction, boolean show) { + // TODO: Not needed anymore once thumbnail is attached to the app. if (show) { pendingTransaction.show(mSurfaceControl); } else { @@ -129,6 +133,9 @@ class AppWindowThumbnail implements Animatable { @Override public void onAnimationLeashDestroyed(Transaction t) { + + // TODO: Once attached to app token, we don't need to hide it immediately if thumbnail + // became visible. t.hide(mSurfaceControl); } diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index de4b426b521d8..0ce37bb63f812 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -1526,7 +1526,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction); if (a != null) { final AnimationAdapter adapter = new LocalAnimationAdapter( - new WindowAnimationSpec(a, new Point()), mService.mSurfaceAnimationRunner); + new WindowAnimationSpec(a, new Point(), + mService.mAppTransition.canSkipFirstFrame()), + mService.mSurfaceAnimationRunner); startAnimation(getPendingTransaction(), adapter, !isVisible()); if (a.getZAdjustment() == Animation.ZORDER_TOP) { mAppAnimator.animLayerAdjustment = 1; diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java index f546240bace49..2173fa3a283d1 100644 --- a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java +++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java @@ -108,5 +108,12 @@ class LocalAnimationAdapter implements AnimationAdapter { * @param currentPlayTime The current time of the animation. */ void apply(Transaction t, SurfaceControl leash, long currentPlayTime); + + /** + * @see AppTransition#canSkipFirstFrame + */ + default boolean canSkipFirstFrame() { + return false; + } } } diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java index a63742e8da873..b44e51d2f04e6 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java @@ -142,6 +142,11 @@ class SurfaceAnimationRunner { // Transaction will be applied in the commit phase. scheduleApplyTransaction(); }); + + if (a.mAnimSpec.canSkipFirstFrame()) { + anim.setCurrentPlayTime(Choreographer.getFrameDelay()); + } + anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java index 9504d456bec8b..20e19f45af6ad 100644 --- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java +++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java @@ -38,10 +38,12 @@ public class WindowAnimationSpec implements AnimationSpec { private Animation mAnimation; private final Point mPosition = new Point(); private final ThreadLocal mThreadLocalTmps = ThreadLocal.withInitial(TmpValues::new); + private final boolean mCanSkipFirstFrame; - public WindowAnimationSpec(Animation animation, Point position) { + public WindowAnimationSpec(Animation animation, Point position, boolean canSkipFirstFrame) { mAnimation = animation; mPosition.set(position.x, position.y); + mCanSkipFirstFrame = canSkipFirstFrame; } @Override @@ -88,6 +90,11 @@ public class WindowAnimationSpec implements AnimationSpec { } } + @Override + public boolean canSkipFirstFrame() { + return mCanSkipFirstFrame; + } + /** * Tries to find a {@link TranslateAnimation} inside the {@code animation}. * diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 69182da9dd10d..b635f43445916 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4276,7 +4276,8 @@ class WindowState extends WindowContainer implements WindowManagerP anim.restrictDuration(MAX_ANIMATION_DURATION); anim.scaleCurrentDuration(mService.getWindowAnimationScaleLocked()); final AnimationAdapter adapter = new LocalAnimationAdapter( - new WindowAnimationSpec(anim, mSurfacePosition), mService.mSurfaceAnimationRunner); + new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */), + mService.mSurfaceAnimationRunner); startAnimation(mPendingTransaction, adapter); commitPendingTransaction(); } 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 c309611bb1393..17fe6427f7560 100644 --- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java +++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java @@ -181,7 +181,7 @@ public class SurfaceAnimationRunnerTest extends WindowTestsBase { final Animation a = new TranslateAnimation(-10, 10, 0, 0); a.initialize(0, 0, 0, 0); a.setDuration(50); - return new WindowAnimationSpec(a, new Point(0, 0)); + return new WindowAnimationSpec(a, new Point(0, 0), false /* canSkipFirstFrame */); } /**