Loading core/java/android/animation/ValueAnimator.java +9 −15 Original line number Original line Diff line number Diff line Loading @@ -522,8 +522,7 @@ public class ValueAnimator extends Animator { * animations possible. * animations possible. * * */ */ private static class AnimationHandler extends Handler private static class AnimationHandler extends Handler implements Runnable { implements Choreographer.OnAnimateListener { // The per-thread list of all active animations // The per-thread list of all active animations private final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>(); private final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>(); Loading @@ -539,7 +538,7 @@ public class ValueAnimator extends Animator { private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>(); private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>(); private final Choreographer mChoreographer; private final Choreographer mChoreographer; private boolean mIsChoreographed; private boolean mAnimationScheduled; private AnimationHandler() { private AnimationHandler() { mChoreographer = Choreographer.getInstance(); mChoreographer = Choreographer.getInstance(); Loading Loading @@ -644,22 +643,17 @@ public class ValueAnimator extends Animator { // If there are still active or delayed animations, schedule a future call to // If there are still active or delayed animations, schedule a future call to // onAnimate to process the next frame of the animations. // onAnimate to process the next frame of the animations. if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) { if (!mAnimationScheduled if (!mIsChoreographed) { && (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty())) { mIsChoreographed = true; mChoreographer.postAnimationCallback(this); mChoreographer.addOnAnimateListener(this); mAnimationScheduled = true; } mChoreographer.scheduleAnimation(); } else { if (mIsChoreographed) { mIsChoreographed = false; mChoreographer.removeOnAnimateListener(this); } } } } } // Called by the Choreographer. @Override @Override public void onAnimate() { public void run() { mAnimationScheduled = false; doAnimationFrame(); doAnimationFrame(); } } } } Loading core/java/android/view/Choreographer.java +75 −244 Original line number Original line Diff line number Diff line Loading @@ -16,8 +16,6 @@ package android.view; package android.view; import com.android.internal.util.ArrayUtils; import android.os.Handler; import android.os.Handler; import android.os.Looper; import android.os.Looper; import android.os.Message; import android.os.Message; Loading @@ -28,8 +26,8 @@ import android.util.Log; /** /** * Coordinates animations and drawing for UI on a particular thread. * Coordinates animations and drawing for UI on a particular thread. * * * This object is thread-safe. Other threads can add and remove listeners * This object is thread-safe. Other threads can post callbacks to run at a later time * or schedule work to occur at a later time on the UI thread. * on the UI thread. * * * Ensuring thread-safety is a little tricky because the {@link DisplayEventReceiver} * Ensuring thread-safety is a little tricky because the {@link DisplayEventReceiver} * can only be accessed from the UI thread so operations that touch the event receiver * can only be accessed from the UI thread so operations that touch the event receiver Loading @@ -42,8 +40,8 @@ public final class Choreographer { private static final boolean DEBUG = false; private static final boolean DEBUG = false; // Amount of time in ms to wait before actually disposing of the display event // Amount of time in ms to wait before actually disposing of the display event // receiver after all listeners have been removed. // receiver when it has not been needed for some time. private static final long DISPOSE_RECEIVER_DELAY = 200; private static final long DISPOSE_RECEIVER_DELAY = 30 * 1000; // The default amount of time in ms between animation frames. // The default amount of time in ms between animation frames. // When vsync is not enabled, we want to have some idea of how long we should // When vsync is not enabled, we want to have some idea of how long we should Loading Loading @@ -96,11 +94,8 @@ public final class Choreographer { private Callback mCallbackPool; private Callback mCallbackPool; private OnAnimateListener[] mOnAnimateListeners; private Callback mAnimationCallbacks; private OnDrawListener[] mOnDrawListeners; private Callback mDrawCallbacks; private Callback mOnAnimateCallbacks; private Callback mOnDrawCallbacks; private boolean mAnimationScheduled; private boolean mAnimationScheduled; private boolean mDrawScheduled; private boolean mDrawScheduled; Loading Loading @@ -159,196 +154,21 @@ public final class Choreographer { sFrameDelay = frameDelay; sFrameDelay = frameDelay; } } /** * Schedules animation (and drawing) to occur on the next frame synchronization boundary. */ public void scheduleAnimation() { synchronized (mLock) { scheduleAnimationLocked(false); } } private void scheduleAnimationLocked(boolean force) { if (!mAnimationScheduled && (force || mOnAnimateListeners != null || mOnAnimateCallbacks != null)) { mAnimationScheduled = true; if (USE_VSYNC) { if (DEBUG) { Log.d(TAG, "Scheduling vsync for animation."); } // If running on the Looper thread, then schedule the vsync immediately, // otherwise post a message to schedule the vsync from the UI thread // as soon as possible. if (!mFrameDisplayEventReceiverNeeded) { mFrameDisplayEventReceiverNeeded = true; if (mFrameDisplayEventReceiver != null) { mHandler.removeMessages(MSG_DO_DISPOSE_RECEIVER); } } if (isRunningOnLooperThreadLocked()) { doScheduleVsyncLocked(); } else { mHandler.sendMessageAtFrontOfQueue( mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC)); } } else { final long now = SystemClock.uptimeMillis(); final long nextAnimationTime = Math.max(mLastAnimationTime + sFrameDelay, now); if (DEBUG) { Log.d(TAG, "Scheduling animation in " + (nextAnimationTime - now) + " ms."); } mHandler.sendEmptyMessageAtTime(MSG_DO_ANIMATION, nextAnimationTime); } } } /** * Returns true if {@link #scheduleAnimation()} has been called but * {@link OnAnimateListener#onAnimate() OnAnimateListener.onAnimate()} has * not yet been called. */ public boolean isAnimationScheduled() { synchronized (mLock) { return mAnimationScheduled; } } /** * Schedules drawing to occur on the next frame synchronization boundary. * Must be called on the UI thread. */ public void scheduleDraw() { synchronized (mLock) { scheduleDrawLocked(); } } private void scheduleDrawLocked() { if (!mDrawScheduled && (mOnDrawListeners != null || mOnDrawCallbacks != null)) { mDrawScheduled = true; if (USE_ANIMATION_TIMER_FOR_DRAW) { scheduleAnimationLocked(true); } else { if (DEBUG) { Log.d(TAG, "Scheduling draw immediately."); } mHandler.sendEmptyMessage(MSG_DO_DRAW); } } } /** * Returns true if {@link #scheduleDraw()} has been called but * {@link OnDrawListener#onDraw() OnDrawListener.onDraw()} has * not yet been called. */ public boolean isDrawScheduled() { synchronized (mLock) { return mDrawScheduled; } } /** * Adds an animation listener. * * @param listener The listener to add. */ public void addOnAnimateListener(OnAnimateListener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } if (DEBUG) { Log.d(TAG, "Adding onAnimate listener: " + listener); } synchronized (mLock) { mOnAnimateListeners = ArrayUtils.appendElement(OnAnimateListener.class, mOnAnimateListeners, listener); } } /** * Removes an animation listener. * * @param listener The listener to remove. */ public void removeOnAnimateListener(OnAnimateListener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } if (DEBUG) { Log.d(TAG, "Removing onAnimate listener: " + listener); } synchronized (mLock) { mOnAnimateListeners = ArrayUtils.removeElement(OnAnimateListener.class, mOnAnimateListeners, listener); stopTimingLoopIfNoListenersOrCallbacksLocked(); } } /** * Adds a draw listener. * * @param listener The listener to add. */ public void addOnDrawListener(OnDrawListener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } if (DEBUG) { Log.d(TAG, "Adding onDraw listener: " + listener); } synchronized (mLock) { mOnDrawListeners = ArrayUtils.appendElement(OnDrawListener.class, mOnDrawListeners, listener); } } /** * Removes a draw listener. * Must be called on the UI thread. * * @param listener The listener to remove. */ public void removeOnDrawListener(OnDrawListener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } if (DEBUG) { Log.d(TAG, "Removing onDraw listener: " + listener); } synchronized (mLock) { mOnDrawListeners = ArrayUtils.removeElement(OnDrawListener.class, mOnDrawListeners, listener); stopTimingLoopIfNoListenersOrCallbacksLocked(); } } /** /** * Posts a callback to run on the next animation cycle and schedules an animation cycle. * Posts a callback to run on the next animation cycle and schedules an animation cycle. * The callback only runs once and then is automatically removed. * The callback only runs once and then is automatically removed. * * * @param runnable The callback to run during the next animation cycle. * @param runnable The callback to run during the next animation cycle. * * * @see #removeOnAnimateCallback * @see #removeAnimationCallback */ */ public void postOnAnimateCallback(Runnable runnable) { public void postAnimationCallback(Runnable runnable) { if (runnable == null) { if (runnable == null) { throw new IllegalArgumentException("runnable must not be null"); throw new IllegalArgumentException("runnable must not be null"); } } synchronized (mLock) { synchronized (mLock) { mOnAnimateCallbacks = addCallbackLocked(mOnAnimateCallbacks, runnable); mAnimationCallbacks = addCallbackLocked(mAnimationCallbacks, runnable); scheduleAnimationLocked(false); scheduleAnimationLocked(); } } } } Loading @@ -359,15 +179,15 @@ public final class Choreographer { * * * @param runnable The animation callback to remove. * @param runnable The animation callback to remove. * * * @see #postOnAnimateCallback * @see #postAnimationCallback */ */ public void removeOnAnimateCallback(Runnable runnable) { public void removeAnimationCallback(Runnable runnable) { if (runnable == null) { if (runnable == null) { throw new IllegalArgumentException("runnable must not be null"); throw new IllegalArgumentException("runnable must not be null"); } } synchronized (mLock) { synchronized (mLock) { mOnAnimateCallbacks = removeCallbackLocked(mOnAnimateCallbacks, runnable); mAnimationCallbacks = removeCallbackLocked(mAnimationCallbacks, runnable); stopTimingLoopIfNoListenersOrCallbacksLocked(); stopTimingLoopIfNoCallbacksLocked(); } } } } Loading @@ -377,14 +197,14 @@ public final class Choreographer { * * * @param runnable The callback to run during the next draw cycle. * @param runnable The callback to run during the next draw cycle. * * * @see #removeOnDrawCallback * @see #removeDrawCallback */ */ public void postOnDrawCallback(Runnable runnable) { public void postDrawCallback(Runnable runnable) { if (runnable == null) { if (runnable == null) { throw new IllegalArgumentException("runnable must not be null"); throw new IllegalArgumentException("runnable must not be null"); } } synchronized (mLock) { synchronized (mLock) { mOnDrawCallbacks = addCallbackLocked(mOnDrawCallbacks, runnable); mDrawCallbacks = addCallbackLocked(mDrawCallbacks, runnable); scheduleDrawLocked(); scheduleDrawLocked(); } } } } Loading @@ -396,15 +216,63 @@ public final class Choreographer { * * * @param runnable The draw callback to remove. * @param runnable The draw callback to remove. * * * @see #postOnDrawCallback * @see #postDrawCallback */ */ public void removeOnDrawCallback(Runnable runnable) { public void removeDrawCallback(Runnable runnable) { if (runnable == null) { if (runnable == null) { throw new IllegalArgumentException("runnable must not be null"); throw new IllegalArgumentException("runnable must not be null"); } } synchronized (mLock) { synchronized (mLock) { mOnDrawCallbacks = removeCallbackLocked(mOnDrawCallbacks, runnable); mDrawCallbacks = removeCallbackLocked(mDrawCallbacks, runnable); stopTimingLoopIfNoListenersOrCallbacksLocked(); stopTimingLoopIfNoCallbacksLocked(); } } private void scheduleAnimationLocked() { if (!mAnimationScheduled) { mAnimationScheduled = true; if (USE_VSYNC) { if (DEBUG) { Log.d(TAG, "Scheduling vsync for animation."); } // If running on the Looper thread, then schedule the vsync immediately, // otherwise post a message to schedule the vsync from the UI thread // as soon as possible. if (!mFrameDisplayEventReceiverNeeded) { mFrameDisplayEventReceiverNeeded = true; if (mFrameDisplayEventReceiver != null) { mHandler.removeMessages(MSG_DO_DISPOSE_RECEIVER); } } if (isRunningOnLooperThreadLocked()) { doScheduleVsyncLocked(); } else { mHandler.sendMessageAtFrontOfQueue( mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC)); } } else { final long now = SystemClock.uptimeMillis(); final long nextAnimationTime = Math.max(mLastAnimationTime + sFrameDelay, now); if (DEBUG) { Log.d(TAG, "Scheduling animation in " + (nextAnimationTime - now) + " ms."); } mHandler.sendEmptyMessageAtTime(MSG_DO_ANIMATION, nextAnimationTime); } } } private void scheduleDrawLocked() { if (!mDrawScheduled) { mDrawScheduled = true; if (USE_ANIMATION_TIMER_FOR_DRAW) { scheduleAnimationLocked(); } else { if (DEBUG) { Log.d(TAG, "Scheduling draw immediately."); } mHandler.sendEmptyMessage(MSG_DO_DRAW); } } } } } Loading @@ -418,7 +286,6 @@ public final class Choreographer { void doAnimationInner() { void doAnimationInner() { final long start; final long start; final OnAnimateListener[] listeners; final Callback callbacks; final Callback callbacks; synchronized (mLock) { synchronized (mLock) { if (!mAnimationScheduled) { if (!mAnimationScheduled) { Loading @@ -433,15 +300,8 @@ public final class Choreographer { } } mLastAnimationTime = start; mLastAnimationTime = start; listeners = mOnAnimateListeners; callbacks = mAnimationCallbacks; callbacks = mOnAnimateCallbacks; mAnimationCallbacks = null; mOnAnimateCallbacks = null; } if (listeners != null) { for (int i = 0; i < listeners.length; i++) { listeners[i].onAnimate(); } } } if (callbacks != null) { if (callbacks != null) { Loading @@ -458,7 +318,6 @@ public final class Choreographer { void doDraw() { void doDraw() { final long start; final long start; final OnDrawListener[] listeners; final Callback callbacks; final Callback callbacks; synchronized (mLock) { synchronized (mLock) { if (!mDrawScheduled) { if (!mDrawScheduled) { Loading @@ -473,15 +332,8 @@ public final class Choreographer { } } mLastDrawTime = start; mLastDrawTime = start; listeners = mOnDrawListeners; callbacks = mDrawCallbacks; callbacks = mOnDrawCallbacks; mDrawCallbacks = null; mOnDrawCallbacks = null; } if (listeners != null) { for (int i = 0; i < listeners.length; i++) { listeners[i].onDraw(); } } } if (callbacks != null) { if (callbacks != null) { Loading Loading @@ -520,9 +372,8 @@ public final class Choreographer { } } } } private void stopTimingLoopIfNoListenersOrCallbacksLocked() { private void stopTimingLoopIfNoCallbacksLocked() { if (mOnAnimateListeners == null && mOnDrawListeners == null if (mAnimationCallbacks == null && mDrawCallbacks == null) { && mOnAnimateCallbacks == null && mOnDrawCallbacks == null) { if (DEBUG) { if (DEBUG) { Log.d(TAG, "Stopping timing loop."); Log.d(TAG, "Stopping timing loop."); } } Loading Loading @@ -627,26 +478,6 @@ public final class Choreographer { mCallbackPool = callback; mCallbackPool = callback; } } /** * Listens for animation frame timing events. */ public static interface OnAnimateListener { /** * Called to animate properties before drawing the frame. */ public void onAnimate(); } /** * Listens for draw frame timing events. */ public static interface OnDrawListener { /** * Called to draw the frame. */ public void onDraw(); } private final class FrameHandler extends Handler { private final class FrameHandler extends Handler { public FrameHandler(Looper looper) { public FrameHandler(Looper looper) { super(looper); super(looper); Loading core/java/android/view/ViewRootImpl.java +29 −9 Original line number Original line Diff line number Diff line Loading @@ -97,8 +97,7 @@ import java.util.List; */ */ @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"}) @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"}) public final class ViewRootImpl extends Handler implements ViewParent, public final class ViewRootImpl extends Handler implements ViewParent, View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks, View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks { Choreographer.OnDrawListener { private static final String TAG = "ViewRootImpl"; private static final String TAG = "ViewRootImpl"; private static final boolean DBG = false; private static final boolean DBG = false; private static final boolean LOCAL_LOGV = false; private static final boolean LOCAL_LOGV = false; Loading Loading @@ -463,8 +462,6 @@ public final class ViewRootImpl extends Handler implements ViewParent, public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this) { synchronized (this) { if (mView == null) { if (mView == null) { mChoreographer.addOnDrawListener(this); mView = view; mView = view; mFallbackEventHandler.setView(view); mFallbackEventHandler.setView(view); mWindowAttributes.copyFrom(attrs); mWindowAttributes.copyFrom(attrs); Loading Loading @@ -841,7 +838,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, public void scheduleTraversals() { public void scheduleTraversals() { if (!mTraversalScheduled) { if (!mTraversalScheduled) { mTraversalScheduled = true; mTraversalScheduled = true; mChoreographer.scheduleDraw(); scheduleFrame(); } } } } Loading @@ -849,8 +846,21 @@ public final class ViewRootImpl extends Handler implements ViewParent, mTraversalScheduled = false; mTraversalScheduled = false; } } @Override void scheduleFrame() { public void onDraw() { if (!mFrameScheduled) { mChoreographer.postDrawCallback(mFrameRunnable); mFrameScheduled = true; } } void unscheduleFrame() { if (mFrameScheduled) { mFrameScheduled = false; mChoreographer.removeDrawCallback(mFrameRunnable); } } void doFrame() { if (mInputEventReceiver != null) { if (mInputEventReceiver != null) { mInputEventReceiver.consumeBatchedInputEvents(); mInputEventReceiver.consumeBatchedInputEvents(); } } Loading Loading @@ -2376,7 +2386,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, mInputChannel = null; mInputChannel = null; } } mChoreographer.removeOnDrawListener(this); unscheduleFrame(); } } void updateConfiguration(Configuration config, boolean force) { void updateConfiguration(Configuration config, boolean force) { Loading Loading @@ -3923,6 +3933,16 @@ public final class ViewRootImpl extends Handler implements ViewParent, } } } } final class FrameRunnable implements Runnable { @Override public void run() { mFrameScheduled = false; doFrame(); } } final FrameRunnable mFrameRunnable = new FrameRunnable(); boolean mFrameScheduled; final class WindowInputEventReceiver extends InputEventReceiver { final class WindowInputEventReceiver extends InputEventReceiver { public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) { public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); super(inputChannel, looper); Loading @@ -3935,7 +3955,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, @Override @Override public void onBatchedInputEventPending() { public void onBatchedInputEventPending() { mChoreographer.scheduleDraw(); scheduleFrame(); } } } } WindowInputEventReceiver mInputEventReceiver; WindowInputEventReceiver mInputEventReceiver; Loading services/java/com/android/server/wm/WindowManagerService.java +21 −11 Original line number Original line Diff line number Diff line Loading @@ -142,8 +142,7 @@ import java.util.List; /** {@hide} */ /** {@hide} */ public class WindowManagerService extends IWindowManager.Stub public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs, implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { Choreographer.OnAnimateListener { static final String TAG = "WindowManager"; static final String TAG = "WindowManager"; static final boolean DEBUG = false; static final boolean DEBUG = false; static final boolean DEBUG_ADD_REMOVE = false; static final boolean DEBUG_ADD_REMOVE = false; Loading Loading @@ -603,6 +602,18 @@ public class WindowManagerService extends IWindowManager.Stub } } private LayoutAndSurfaceFields mInnerFields = new LayoutAndSurfaceFields(); private LayoutAndSurfaceFields mInnerFields = new LayoutAndSurfaceFields(); private final class AnimationRunnable implements Runnable { @Override public void run() { synchronized(mWindowMap) { mAnimationScheduled = false; performLayoutAndPlaceSurfacesLocked(); } } } final AnimationRunnable mAnimationRunnable = new AnimationRunnable(); boolean mAnimationScheduled; final class DragInputEventReceiver extends InputEventReceiver { final class DragInputEventReceiver extends InputEventReceiver { public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); super(inputChannel, looper); Loading Loading @@ -724,7 +735,6 @@ public class WindowManagerService extends IWindowManager.Stub Looper.prepare(); Looper.prepare(); WindowManagerService s = new WindowManagerService(mContext, mPM, WindowManagerService s = new WindowManagerService(mContext, mPM, mHaveInputMethods, mAllowBootMessages); mHaveInputMethods, mAllowBootMessages); s.mChoreographer.addOnAnimateListener(s); android.os.Process.setThreadPriority( android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_DISPLAY); android.os.Process.THREAD_PRIORITY_DISPLAY); android.os.Process.setCanSelfBackground(false); android.os.Process.setCanSelfBackground(false); Loading Loading @@ -5441,7 +5451,7 @@ public class WindowManagerService extends IWindowManager.Stub if (mScreenRotationAnimation.setRotation(rotation, mFxSession, if (mScreenRotationAnimation.setRotation(rotation, mFxSession, MAX_ANIMATION_DURATION, mTransitionAnimationScale, MAX_ANIMATION_DURATION, mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { mCurDisplayWidth, mCurDisplayHeight)) { mChoreographer.scheduleAnimation(); scheduleAnimationLocked(); } } } } Surface.setOrientation(0, rotation); Surface.setOrientation(0, rotation); Loading Loading @@ -6882,7 +6892,7 @@ public class WindowManagerService extends IWindowManager.Stub case FORCE_GC: { case FORCE_GC: { synchronized(mWindowMap) { synchronized(mWindowMap) { if (mChoreographer.isAnimationScheduled()) { if (mAnimationScheduled) { // If we are animating, don't do the gc now but // If we are animating, don't do the gc now but // delay a bit so we don't interrupt the animation. // delay a bit so we don't interrupt the animation. mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), Loading Loading @@ -8980,7 +8990,7 @@ public class WindowManagerService extends IWindowManager.Stub if (needRelayout) { if (needRelayout) { requestTraversalLocked(); requestTraversalLocked(); } else if (mInnerFields.mAnimating) { } else if (mInnerFields.mAnimating) { mChoreographer.scheduleAnimation(); scheduleAnimationLocked(); } } // Finally update all input windows now that the window changes have stabilized. // Finally update all input windows now that the window changes have stabilized. Loading Loading @@ -9100,10 +9110,10 @@ public class WindowManagerService extends IWindowManager.Stub } } } } @Override void scheduleAnimationLocked() { public void onAnimate() { if (!mAnimationScheduled) { synchronized(mWindowMap) { mChoreographer.postAnimationCallback(mAnimationRunnable); performLayoutAndPlaceSurfacesLocked(); mAnimationScheduled = true; } } } } Loading Loading @@ -9423,7 +9433,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { mChoreographer.scheduleAnimation(); scheduleAnimationLocked(); } else { } else { mScreenRotationAnimation = null; mScreenRotationAnimation = null; updateRotation = true; updateRotation = true; Loading services/java/com/android/server/wm/WindowState.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -1593,7 +1593,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true); mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true); } } if (requestAnim) { if (requestAnim) { mService.mChoreographer.scheduleAnimation(); mService.scheduleAnimationLocked(); } } return true; return true; } } Loading Loading @@ -1634,7 +1634,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } } } if (requestAnim) { if (requestAnim) { mService.mChoreographer.scheduleAnimation(); mService.scheduleAnimationLocked(); } } return true; return true; } } Loading Loading
core/java/android/animation/ValueAnimator.java +9 −15 Original line number Original line Diff line number Diff line Loading @@ -522,8 +522,7 @@ public class ValueAnimator extends Animator { * animations possible. * animations possible. * * */ */ private static class AnimationHandler extends Handler private static class AnimationHandler extends Handler implements Runnable { implements Choreographer.OnAnimateListener { // The per-thread list of all active animations // The per-thread list of all active animations private final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>(); private final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>(); Loading @@ -539,7 +538,7 @@ public class ValueAnimator extends Animator { private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>(); private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>(); private final Choreographer mChoreographer; private final Choreographer mChoreographer; private boolean mIsChoreographed; private boolean mAnimationScheduled; private AnimationHandler() { private AnimationHandler() { mChoreographer = Choreographer.getInstance(); mChoreographer = Choreographer.getInstance(); Loading Loading @@ -644,22 +643,17 @@ public class ValueAnimator extends Animator { // If there are still active or delayed animations, schedule a future call to // If there are still active or delayed animations, schedule a future call to // onAnimate to process the next frame of the animations. // onAnimate to process the next frame of the animations. if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) { if (!mAnimationScheduled if (!mIsChoreographed) { && (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty())) { mIsChoreographed = true; mChoreographer.postAnimationCallback(this); mChoreographer.addOnAnimateListener(this); mAnimationScheduled = true; } mChoreographer.scheduleAnimation(); } else { if (mIsChoreographed) { mIsChoreographed = false; mChoreographer.removeOnAnimateListener(this); } } } } } // Called by the Choreographer. @Override @Override public void onAnimate() { public void run() { mAnimationScheduled = false; doAnimationFrame(); doAnimationFrame(); } } } } Loading
core/java/android/view/Choreographer.java +75 −244 Original line number Original line Diff line number Diff line Loading @@ -16,8 +16,6 @@ package android.view; package android.view; import com.android.internal.util.ArrayUtils; import android.os.Handler; import android.os.Handler; import android.os.Looper; import android.os.Looper; import android.os.Message; import android.os.Message; Loading @@ -28,8 +26,8 @@ import android.util.Log; /** /** * Coordinates animations and drawing for UI on a particular thread. * Coordinates animations and drawing for UI on a particular thread. * * * This object is thread-safe. Other threads can add and remove listeners * This object is thread-safe. Other threads can post callbacks to run at a later time * or schedule work to occur at a later time on the UI thread. * on the UI thread. * * * Ensuring thread-safety is a little tricky because the {@link DisplayEventReceiver} * Ensuring thread-safety is a little tricky because the {@link DisplayEventReceiver} * can only be accessed from the UI thread so operations that touch the event receiver * can only be accessed from the UI thread so operations that touch the event receiver Loading @@ -42,8 +40,8 @@ public final class Choreographer { private static final boolean DEBUG = false; private static final boolean DEBUG = false; // Amount of time in ms to wait before actually disposing of the display event // Amount of time in ms to wait before actually disposing of the display event // receiver after all listeners have been removed. // receiver when it has not been needed for some time. private static final long DISPOSE_RECEIVER_DELAY = 200; private static final long DISPOSE_RECEIVER_DELAY = 30 * 1000; // The default amount of time in ms between animation frames. // The default amount of time in ms between animation frames. // When vsync is not enabled, we want to have some idea of how long we should // When vsync is not enabled, we want to have some idea of how long we should Loading Loading @@ -96,11 +94,8 @@ public final class Choreographer { private Callback mCallbackPool; private Callback mCallbackPool; private OnAnimateListener[] mOnAnimateListeners; private Callback mAnimationCallbacks; private OnDrawListener[] mOnDrawListeners; private Callback mDrawCallbacks; private Callback mOnAnimateCallbacks; private Callback mOnDrawCallbacks; private boolean mAnimationScheduled; private boolean mAnimationScheduled; private boolean mDrawScheduled; private boolean mDrawScheduled; Loading Loading @@ -159,196 +154,21 @@ public final class Choreographer { sFrameDelay = frameDelay; sFrameDelay = frameDelay; } } /** * Schedules animation (and drawing) to occur on the next frame synchronization boundary. */ public void scheduleAnimation() { synchronized (mLock) { scheduleAnimationLocked(false); } } private void scheduleAnimationLocked(boolean force) { if (!mAnimationScheduled && (force || mOnAnimateListeners != null || mOnAnimateCallbacks != null)) { mAnimationScheduled = true; if (USE_VSYNC) { if (DEBUG) { Log.d(TAG, "Scheduling vsync for animation."); } // If running on the Looper thread, then schedule the vsync immediately, // otherwise post a message to schedule the vsync from the UI thread // as soon as possible. if (!mFrameDisplayEventReceiverNeeded) { mFrameDisplayEventReceiverNeeded = true; if (mFrameDisplayEventReceiver != null) { mHandler.removeMessages(MSG_DO_DISPOSE_RECEIVER); } } if (isRunningOnLooperThreadLocked()) { doScheduleVsyncLocked(); } else { mHandler.sendMessageAtFrontOfQueue( mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC)); } } else { final long now = SystemClock.uptimeMillis(); final long nextAnimationTime = Math.max(mLastAnimationTime + sFrameDelay, now); if (DEBUG) { Log.d(TAG, "Scheduling animation in " + (nextAnimationTime - now) + " ms."); } mHandler.sendEmptyMessageAtTime(MSG_DO_ANIMATION, nextAnimationTime); } } } /** * Returns true if {@link #scheduleAnimation()} has been called but * {@link OnAnimateListener#onAnimate() OnAnimateListener.onAnimate()} has * not yet been called. */ public boolean isAnimationScheduled() { synchronized (mLock) { return mAnimationScheduled; } } /** * Schedules drawing to occur on the next frame synchronization boundary. * Must be called on the UI thread. */ public void scheduleDraw() { synchronized (mLock) { scheduleDrawLocked(); } } private void scheduleDrawLocked() { if (!mDrawScheduled && (mOnDrawListeners != null || mOnDrawCallbacks != null)) { mDrawScheduled = true; if (USE_ANIMATION_TIMER_FOR_DRAW) { scheduleAnimationLocked(true); } else { if (DEBUG) { Log.d(TAG, "Scheduling draw immediately."); } mHandler.sendEmptyMessage(MSG_DO_DRAW); } } } /** * Returns true if {@link #scheduleDraw()} has been called but * {@link OnDrawListener#onDraw() OnDrawListener.onDraw()} has * not yet been called. */ public boolean isDrawScheduled() { synchronized (mLock) { return mDrawScheduled; } } /** * Adds an animation listener. * * @param listener The listener to add. */ public void addOnAnimateListener(OnAnimateListener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } if (DEBUG) { Log.d(TAG, "Adding onAnimate listener: " + listener); } synchronized (mLock) { mOnAnimateListeners = ArrayUtils.appendElement(OnAnimateListener.class, mOnAnimateListeners, listener); } } /** * Removes an animation listener. * * @param listener The listener to remove. */ public void removeOnAnimateListener(OnAnimateListener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } if (DEBUG) { Log.d(TAG, "Removing onAnimate listener: " + listener); } synchronized (mLock) { mOnAnimateListeners = ArrayUtils.removeElement(OnAnimateListener.class, mOnAnimateListeners, listener); stopTimingLoopIfNoListenersOrCallbacksLocked(); } } /** * Adds a draw listener. * * @param listener The listener to add. */ public void addOnDrawListener(OnDrawListener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } if (DEBUG) { Log.d(TAG, "Adding onDraw listener: " + listener); } synchronized (mLock) { mOnDrawListeners = ArrayUtils.appendElement(OnDrawListener.class, mOnDrawListeners, listener); } } /** * Removes a draw listener. * Must be called on the UI thread. * * @param listener The listener to remove. */ public void removeOnDrawListener(OnDrawListener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } if (DEBUG) { Log.d(TAG, "Removing onDraw listener: " + listener); } synchronized (mLock) { mOnDrawListeners = ArrayUtils.removeElement(OnDrawListener.class, mOnDrawListeners, listener); stopTimingLoopIfNoListenersOrCallbacksLocked(); } } /** /** * Posts a callback to run on the next animation cycle and schedules an animation cycle. * Posts a callback to run on the next animation cycle and schedules an animation cycle. * The callback only runs once and then is automatically removed. * The callback only runs once and then is automatically removed. * * * @param runnable The callback to run during the next animation cycle. * @param runnable The callback to run during the next animation cycle. * * * @see #removeOnAnimateCallback * @see #removeAnimationCallback */ */ public void postOnAnimateCallback(Runnable runnable) { public void postAnimationCallback(Runnable runnable) { if (runnable == null) { if (runnable == null) { throw new IllegalArgumentException("runnable must not be null"); throw new IllegalArgumentException("runnable must not be null"); } } synchronized (mLock) { synchronized (mLock) { mOnAnimateCallbacks = addCallbackLocked(mOnAnimateCallbacks, runnable); mAnimationCallbacks = addCallbackLocked(mAnimationCallbacks, runnable); scheduleAnimationLocked(false); scheduleAnimationLocked(); } } } } Loading @@ -359,15 +179,15 @@ public final class Choreographer { * * * @param runnable The animation callback to remove. * @param runnable The animation callback to remove. * * * @see #postOnAnimateCallback * @see #postAnimationCallback */ */ public void removeOnAnimateCallback(Runnable runnable) { public void removeAnimationCallback(Runnable runnable) { if (runnable == null) { if (runnable == null) { throw new IllegalArgumentException("runnable must not be null"); throw new IllegalArgumentException("runnable must not be null"); } } synchronized (mLock) { synchronized (mLock) { mOnAnimateCallbacks = removeCallbackLocked(mOnAnimateCallbacks, runnable); mAnimationCallbacks = removeCallbackLocked(mAnimationCallbacks, runnable); stopTimingLoopIfNoListenersOrCallbacksLocked(); stopTimingLoopIfNoCallbacksLocked(); } } } } Loading @@ -377,14 +197,14 @@ public final class Choreographer { * * * @param runnable The callback to run during the next draw cycle. * @param runnable The callback to run during the next draw cycle. * * * @see #removeOnDrawCallback * @see #removeDrawCallback */ */ public void postOnDrawCallback(Runnable runnable) { public void postDrawCallback(Runnable runnable) { if (runnable == null) { if (runnable == null) { throw new IllegalArgumentException("runnable must not be null"); throw new IllegalArgumentException("runnable must not be null"); } } synchronized (mLock) { synchronized (mLock) { mOnDrawCallbacks = addCallbackLocked(mOnDrawCallbacks, runnable); mDrawCallbacks = addCallbackLocked(mDrawCallbacks, runnable); scheduleDrawLocked(); scheduleDrawLocked(); } } } } Loading @@ -396,15 +216,63 @@ public final class Choreographer { * * * @param runnable The draw callback to remove. * @param runnable The draw callback to remove. * * * @see #postOnDrawCallback * @see #postDrawCallback */ */ public void removeOnDrawCallback(Runnable runnable) { public void removeDrawCallback(Runnable runnable) { if (runnable == null) { if (runnable == null) { throw new IllegalArgumentException("runnable must not be null"); throw new IllegalArgumentException("runnable must not be null"); } } synchronized (mLock) { synchronized (mLock) { mOnDrawCallbacks = removeCallbackLocked(mOnDrawCallbacks, runnable); mDrawCallbacks = removeCallbackLocked(mDrawCallbacks, runnable); stopTimingLoopIfNoListenersOrCallbacksLocked(); stopTimingLoopIfNoCallbacksLocked(); } } private void scheduleAnimationLocked() { if (!mAnimationScheduled) { mAnimationScheduled = true; if (USE_VSYNC) { if (DEBUG) { Log.d(TAG, "Scheduling vsync for animation."); } // If running on the Looper thread, then schedule the vsync immediately, // otherwise post a message to schedule the vsync from the UI thread // as soon as possible. if (!mFrameDisplayEventReceiverNeeded) { mFrameDisplayEventReceiverNeeded = true; if (mFrameDisplayEventReceiver != null) { mHandler.removeMessages(MSG_DO_DISPOSE_RECEIVER); } } if (isRunningOnLooperThreadLocked()) { doScheduleVsyncLocked(); } else { mHandler.sendMessageAtFrontOfQueue( mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC)); } } else { final long now = SystemClock.uptimeMillis(); final long nextAnimationTime = Math.max(mLastAnimationTime + sFrameDelay, now); if (DEBUG) { Log.d(TAG, "Scheduling animation in " + (nextAnimationTime - now) + " ms."); } mHandler.sendEmptyMessageAtTime(MSG_DO_ANIMATION, nextAnimationTime); } } } private void scheduleDrawLocked() { if (!mDrawScheduled) { mDrawScheduled = true; if (USE_ANIMATION_TIMER_FOR_DRAW) { scheduleAnimationLocked(); } else { if (DEBUG) { Log.d(TAG, "Scheduling draw immediately."); } mHandler.sendEmptyMessage(MSG_DO_DRAW); } } } } } Loading @@ -418,7 +286,6 @@ public final class Choreographer { void doAnimationInner() { void doAnimationInner() { final long start; final long start; final OnAnimateListener[] listeners; final Callback callbacks; final Callback callbacks; synchronized (mLock) { synchronized (mLock) { if (!mAnimationScheduled) { if (!mAnimationScheduled) { Loading @@ -433,15 +300,8 @@ public final class Choreographer { } } mLastAnimationTime = start; mLastAnimationTime = start; listeners = mOnAnimateListeners; callbacks = mAnimationCallbacks; callbacks = mOnAnimateCallbacks; mAnimationCallbacks = null; mOnAnimateCallbacks = null; } if (listeners != null) { for (int i = 0; i < listeners.length; i++) { listeners[i].onAnimate(); } } } if (callbacks != null) { if (callbacks != null) { Loading @@ -458,7 +318,6 @@ public final class Choreographer { void doDraw() { void doDraw() { final long start; final long start; final OnDrawListener[] listeners; final Callback callbacks; final Callback callbacks; synchronized (mLock) { synchronized (mLock) { if (!mDrawScheduled) { if (!mDrawScheduled) { Loading @@ -473,15 +332,8 @@ public final class Choreographer { } } mLastDrawTime = start; mLastDrawTime = start; listeners = mOnDrawListeners; callbacks = mDrawCallbacks; callbacks = mOnDrawCallbacks; mDrawCallbacks = null; mOnDrawCallbacks = null; } if (listeners != null) { for (int i = 0; i < listeners.length; i++) { listeners[i].onDraw(); } } } if (callbacks != null) { if (callbacks != null) { Loading Loading @@ -520,9 +372,8 @@ public final class Choreographer { } } } } private void stopTimingLoopIfNoListenersOrCallbacksLocked() { private void stopTimingLoopIfNoCallbacksLocked() { if (mOnAnimateListeners == null && mOnDrawListeners == null if (mAnimationCallbacks == null && mDrawCallbacks == null) { && mOnAnimateCallbacks == null && mOnDrawCallbacks == null) { if (DEBUG) { if (DEBUG) { Log.d(TAG, "Stopping timing loop."); Log.d(TAG, "Stopping timing loop."); } } Loading Loading @@ -627,26 +478,6 @@ public final class Choreographer { mCallbackPool = callback; mCallbackPool = callback; } } /** * Listens for animation frame timing events. */ public static interface OnAnimateListener { /** * Called to animate properties before drawing the frame. */ public void onAnimate(); } /** * Listens for draw frame timing events. */ public static interface OnDrawListener { /** * Called to draw the frame. */ public void onDraw(); } private final class FrameHandler extends Handler { private final class FrameHandler extends Handler { public FrameHandler(Looper looper) { public FrameHandler(Looper looper) { super(looper); super(looper); Loading
core/java/android/view/ViewRootImpl.java +29 −9 Original line number Original line Diff line number Diff line Loading @@ -97,8 +97,7 @@ import java.util.List; */ */ @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"}) @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"}) public final class ViewRootImpl extends Handler implements ViewParent, public final class ViewRootImpl extends Handler implements ViewParent, View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks, View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks { Choreographer.OnDrawListener { private static final String TAG = "ViewRootImpl"; private static final String TAG = "ViewRootImpl"; private static final boolean DBG = false; private static final boolean DBG = false; private static final boolean LOCAL_LOGV = false; private static final boolean LOCAL_LOGV = false; Loading Loading @@ -463,8 +462,6 @@ public final class ViewRootImpl extends Handler implements ViewParent, public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this) { synchronized (this) { if (mView == null) { if (mView == null) { mChoreographer.addOnDrawListener(this); mView = view; mView = view; mFallbackEventHandler.setView(view); mFallbackEventHandler.setView(view); mWindowAttributes.copyFrom(attrs); mWindowAttributes.copyFrom(attrs); Loading Loading @@ -841,7 +838,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, public void scheduleTraversals() { public void scheduleTraversals() { if (!mTraversalScheduled) { if (!mTraversalScheduled) { mTraversalScheduled = true; mTraversalScheduled = true; mChoreographer.scheduleDraw(); scheduleFrame(); } } } } Loading @@ -849,8 +846,21 @@ public final class ViewRootImpl extends Handler implements ViewParent, mTraversalScheduled = false; mTraversalScheduled = false; } } @Override void scheduleFrame() { public void onDraw() { if (!mFrameScheduled) { mChoreographer.postDrawCallback(mFrameRunnable); mFrameScheduled = true; } } void unscheduleFrame() { if (mFrameScheduled) { mFrameScheduled = false; mChoreographer.removeDrawCallback(mFrameRunnable); } } void doFrame() { if (mInputEventReceiver != null) { if (mInputEventReceiver != null) { mInputEventReceiver.consumeBatchedInputEvents(); mInputEventReceiver.consumeBatchedInputEvents(); } } Loading Loading @@ -2376,7 +2386,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, mInputChannel = null; mInputChannel = null; } } mChoreographer.removeOnDrawListener(this); unscheduleFrame(); } } void updateConfiguration(Configuration config, boolean force) { void updateConfiguration(Configuration config, boolean force) { Loading Loading @@ -3923,6 +3933,16 @@ public final class ViewRootImpl extends Handler implements ViewParent, } } } } final class FrameRunnable implements Runnable { @Override public void run() { mFrameScheduled = false; doFrame(); } } final FrameRunnable mFrameRunnable = new FrameRunnable(); boolean mFrameScheduled; final class WindowInputEventReceiver extends InputEventReceiver { final class WindowInputEventReceiver extends InputEventReceiver { public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) { public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); super(inputChannel, looper); Loading @@ -3935,7 +3955,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, @Override @Override public void onBatchedInputEventPending() { public void onBatchedInputEventPending() { mChoreographer.scheduleDraw(); scheduleFrame(); } } } } WindowInputEventReceiver mInputEventReceiver; WindowInputEventReceiver mInputEventReceiver; Loading
services/java/com/android/server/wm/WindowManagerService.java +21 −11 Original line number Original line Diff line number Diff line Loading @@ -142,8 +142,7 @@ import java.util.List; /** {@hide} */ /** {@hide} */ public class WindowManagerService extends IWindowManager.Stub public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs, implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs { Choreographer.OnAnimateListener { static final String TAG = "WindowManager"; static final String TAG = "WindowManager"; static final boolean DEBUG = false; static final boolean DEBUG = false; static final boolean DEBUG_ADD_REMOVE = false; static final boolean DEBUG_ADD_REMOVE = false; Loading Loading @@ -603,6 +602,18 @@ public class WindowManagerService extends IWindowManager.Stub } } private LayoutAndSurfaceFields mInnerFields = new LayoutAndSurfaceFields(); private LayoutAndSurfaceFields mInnerFields = new LayoutAndSurfaceFields(); private final class AnimationRunnable implements Runnable { @Override public void run() { synchronized(mWindowMap) { mAnimationScheduled = false; performLayoutAndPlaceSurfacesLocked(); } } } final AnimationRunnable mAnimationRunnable = new AnimationRunnable(); boolean mAnimationScheduled; final class DragInputEventReceiver extends InputEventReceiver { final class DragInputEventReceiver extends InputEventReceiver { public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); super(inputChannel, looper); Loading Loading @@ -724,7 +735,6 @@ public class WindowManagerService extends IWindowManager.Stub Looper.prepare(); Looper.prepare(); WindowManagerService s = new WindowManagerService(mContext, mPM, WindowManagerService s = new WindowManagerService(mContext, mPM, mHaveInputMethods, mAllowBootMessages); mHaveInputMethods, mAllowBootMessages); s.mChoreographer.addOnAnimateListener(s); android.os.Process.setThreadPriority( android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_DISPLAY); android.os.Process.THREAD_PRIORITY_DISPLAY); android.os.Process.setCanSelfBackground(false); android.os.Process.setCanSelfBackground(false); Loading Loading @@ -5441,7 +5451,7 @@ public class WindowManagerService extends IWindowManager.Stub if (mScreenRotationAnimation.setRotation(rotation, mFxSession, if (mScreenRotationAnimation.setRotation(rotation, mFxSession, MAX_ANIMATION_DURATION, mTransitionAnimationScale, MAX_ANIMATION_DURATION, mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { mCurDisplayWidth, mCurDisplayHeight)) { mChoreographer.scheduleAnimation(); scheduleAnimationLocked(); } } } } Surface.setOrientation(0, rotation); Surface.setOrientation(0, rotation); Loading Loading @@ -6882,7 +6892,7 @@ public class WindowManagerService extends IWindowManager.Stub case FORCE_GC: { case FORCE_GC: { synchronized(mWindowMap) { synchronized(mWindowMap) { if (mChoreographer.isAnimationScheduled()) { if (mAnimationScheduled) { // If we are animating, don't do the gc now but // If we are animating, don't do the gc now but // delay a bit so we don't interrupt the animation. // delay a bit so we don't interrupt the animation. mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), Loading Loading @@ -8980,7 +8990,7 @@ public class WindowManagerService extends IWindowManager.Stub if (needRelayout) { if (needRelayout) { requestTraversalLocked(); requestTraversalLocked(); } else if (mInnerFields.mAnimating) { } else if (mInnerFields.mAnimating) { mChoreographer.scheduleAnimation(); scheduleAnimationLocked(); } } // Finally update all input windows now that the window changes have stabilized. // Finally update all input windows now that the window changes have stabilized. Loading Loading @@ -9100,10 +9110,10 @@ public class WindowManagerService extends IWindowManager.Stub } } } } @Override void scheduleAnimationLocked() { public void onAnimate() { if (!mAnimationScheduled) { synchronized(mWindowMap) { mChoreographer.postAnimationCallback(mAnimationRunnable); performLayoutAndPlaceSurfacesLocked(); mAnimationScheduled = true; } } } } Loading Loading @@ -9423,7 +9433,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation"); if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { mChoreographer.scheduleAnimation(); scheduleAnimationLocked(); } else { } else { mScreenRotationAnimation = null; mScreenRotationAnimation = null; updateRotation = true; updateRotation = true; Loading
services/java/com/android/server/wm/WindowState.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -1593,7 +1593,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true); mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true); } } if (requestAnim) { if (requestAnim) { mService.mChoreographer.scheduleAnimation(); mService.scheduleAnimationLocked(); } } return true; return true; } } Loading Loading @@ -1634,7 +1634,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } } } if (requestAnim) { if (requestAnim) { mService.mChoreographer.scheduleAnimation(); mService.scheduleAnimationLocked(); } } return true; return true; } } Loading