From 561eeb5e749c1213c71c638ef76088e75b9acd70 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Fri, 28 Apr 2017 16:39:19 +0200 Subject: [PATCH] Split out whether frame callback and tick is scheduled Since the animation/gesture for screen zoom is running at vsync-app, calling WMS.scheduleAnimation will schedule only at the next frame. However, in the next frame, only the frame callback is handled but not the tick yet, however mAnimationScheduled was still true. Thus, the request to schedule another frame callback is ignored, and then the things get updated only every 2nd frame. Fix this by splitting the information whether the frame callback is scheduled or the actual tick. Test: Use accessibility screen zoom, make sure gestures are smooth. Fixes: 37476440 Change-Id: I2301fab5bf3f3b896d4aa131fb041b89572fa3a7 --- .../com/android/server/wm/WindowAnimator.java | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 1367a06eb1109..067cc0905bd3d 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -87,8 +87,18 @@ public class WindowAnimator { private final SurfaceFlingerVsyncChoreographer mSfChoreographer; private Choreographer mChoreographer; - private boolean mAnimationScheduled; + /** + * 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). + */ + private boolean mAnimationFrameCallbackScheduled; + + /** + * Indicates whether we have an animation tick scheduled. The tick is the thing that actually + * executes the animation step, which will happen at vsync-sf. + */ + private boolean mAnimationTickScheduled; WindowAnimator(final WindowManagerService service) { mService = service; @@ -104,13 +114,20 @@ public class WindowAnimator { mService.getDefaultDisplayContentLocked().getDisplay(), mChoreographer); mAnimationTick = () -> { synchronized (mService.mWindowMap) { - mAnimationScheduled = false; + mAnimationTickScheduled = false; animateLocked(mCurrentFrameTime); } }; mAnimationFrameCallback = frameTimeNs -> { - mCurrentFrameTime = frameTimeNs; - mSfChoreographer.scheduleAtSfVsync(mAnimationTick); + synchronized (mService.mWindowMap) { + mCurrentFrameTime = frameTimeNs; + mAnimationFrameCallbackScheduled = false; + if (mAnimationTickScheduled) { + return; + } + mAnimationTickScheduled = true; + mSfChoreographer.scheduleAtSfVsync(mAnimationTick); + } }; } @@ -371,8 +388,8 @@ public class WindowAnimator { } void scheduleAnimation() { - if (!mAnimationScheduled) { - mAnimationScheduled = true; + if (!mAnimationFrameCallbackScheduled) { + mAnimationFrameCallbackScheduled = true; mChoreographer.postFrameCallback(mAnimationFrameCallback); } } @@ -386,7 +403,7 @@ public class WindowAnimator { } boolean isAnimationScheduled() { - return mAnimationScheduled; + return mAnimationFrameCallbackScheduled || mAnimationTickScheduled; } Choreographer getChoreographer() {