Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4c0a22a authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

Merge "Simplify Choreographer API."

parents 019ace3e 4a06c800
Loading
Loading
Loading
Loading
+9 −15
Original line number Original line Diff line number Diff line
@@ -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>();


@@ -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();
@@ -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();
        }
        }
    }
    }
+75 −244
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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
@@ -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
@@ -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;
@@ -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();
        }
        }
    }
    }


@@ -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();
        }
        }
    }
    }


@@ -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();
        }
        }
    }
    }
@@ -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);
            }
        }
        }
    }
    }


@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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.");
            }
            }
@@ -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);
+29 −9
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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);
@@ -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();
        }
        }
    }
    }


@@ -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();
        }
        }
@@ -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) {
@@ -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);
@@ -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;
+21 −11
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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);
@@ -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);
@@ -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);
@@ -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),
@@ -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.
@@ -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;
        }
        }
    }
    }


@@ -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;
+2 −2
Original line number Original line Diff line number Diff line
@@ -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;
    }
    }
@@ -1634,7 +1634,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
            }
            }
        }
        }
        if (requestAnim) {
        if (requestAnim) {
            mService.mChoreographer.scheduleAnimation();
            mService.scheduleAnimationLocked();
        }
        }
        return true;
        return true;
    }
    }