diff options
| author | Jeff Brown <jeffbrown@google.com> | 2012-02-15 15:06:01 -0800 |
|---|---|---|
| committer | Jeff Brown <jeffbrown@google.com> | 2012-02-15 15:06:01 -0800 |
| commit | 4a06c8008b2edd6677f9a411af79b0a4971b87fe (patch) | |
| tree | ce3bca001e3f2a7778d39be2cb5049f7b1620e16 /core | |
| parent | fef3d62b16bccd9ef7a32c2e1da94f694b34c405 (diff) | |
| download | frameworks_base-4a06c8008b2edd6677f9a411af79b0a4971b87fe.zip frameworks_base-4a06c8008b2edd6677f9a411af79b0a4971b87fe.tar.gz frameworks_base-4a06c8008b2edd6677f9a411af79b0a4971b87fe.tar.bz2 | |
Simplify Choreographer API.
Removed the listeners and schedule animation / draw methods.
Instead all requests are posted as one-shot callbacks, which is a
better match for how clients actually use the Choreographer.
Bug: 5721047
Change-Id: I113180b2713a300e4444d0d987f52b8157b7ac15
Diffstat (limited to 'core')
| -rwxr-xr-x | core/java/android/animation/ValueAnimator.java | 24 | ||||
| -rw-r--r-- | core/java/android/view/Choreographer.java | 319 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 38 |
3 files changed, 113 insertions, 268 deletions
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index cc1efb9..6fbeee3 100755 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -522,8 +522,7 @@ public class ValueAnimator extends Animator { * animations possible. * */ - private static class AnimationHandler extends Handler - implements Choreographer.OnAnimateListener { + private static class AnimationHandler extends Handler implements Runnable { // The per-thread list of all active animations 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 Choreographer mChoreographer; - private boolean mIsChoreographed; + private boolean mAnimationScheduled; private AnimationHandler() { 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 // onAnimate to process the next frame of the animations. - if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) { - if (!mIsChoreographed) { - mIsChoreographed = true; - mChoreographer.addOnAnimateListener(this); - } - mChoreographer.scheduleAnimation(); - } else { - if (mIsChoreographed) { - mIsChoreographed = false; - mChoreographer.removeOnAnimateListener(this); - } + if (!mAnimationScheduled + && (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty())) { + mChoreographer.postAnimationCallback(this); + mAnimationScheduled = true; } } + // Called by the Choreographer. @Override - public void onAnimate() { + public void run() { + mAnimationScheduled = false; doAnimationFrame(); } } diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 658da2f..917389c 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -16,8 +16,6 @@ package android.view; -import com.android.internal.util.ArrayUtils; - import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -28,8 +26,8 @@ import android.util.Log; /** * Coordinates animations and drawing for UI on a particular thread. * - * This object is thread-safe. Other threads can add and remove listeners - * or schedule work to occur at a later time on the UI thread. + * This object is thread-safe. Other threads can post callbacks to run at a later time + * on the UI thread. * * 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 @@ -42,8 +40,8 @@ public final class Choreographer { private static final boolean DEBUG = false; // Amount of time in ms to wait before actually disposing of the display event - // receiver after all listeners have been removed. - private static final long DISPOSE_RECEIVER_DELAY = 200; + // receiver when it has not been needed for some time. + private static final long DISPOSE_RECEIVER_DELAY = 30 * 1000; // 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 @@ -96,11 +94,8 @@ public final class Choreographer { private Callback mCallbackPool; - private OnAnimateListener[] mOnAnimateListeners; - private OnDrawListener[] mOnDrawListeners; - - private Callback mOnAnimateCallbacks; - private Callback mOnDrawCallbacks; + private Callback mAnimationCallbacks; + private Callback mDrawCallbacks; private boolean mAnimationScheduled; private boolean mDrawScheduled; @@ -160,195 +155,20 @@ public final class Choreographer { } /** - * 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. * The callback only runs once and then is automatically removed. * * @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) { throw new IllegalArgumentException("runnable must not be null"); } synchronized (mLock) { - mOnAnimateCallbacks = addCallbackLocked(mOnAnimateCallbacks, runnable); - scheduleAnimationLocked(false); + mAnimationCallbacks = addCallbackLocked(mAnimationCallbacks, runnable); + scheduleAnimationLocked(); } } @@ -359,15 +179,15 @@ public final class Choreographer { * * @param runnable The animation callback to remove. * - * @see #postOnAnimateCallback + * @see #postAnimationCallback */ - public void removeOnAnimateCallback(Runnable runnable) { + public void removeAnimationCallback(Runnable runnable) { if (runnable == null) { throw new IllegalArgumentException("runnable must not be null"); } synchronized (mLock) { - mOnAnimateCallbacks = removeCallbackLocked(mOnAnimateCallbacks, runnable); - stopTimingLoopIfNoListenersOrCallbacksLocked(); + mAnimationCallbacks = removeCallbackLocked(mAnimationCallbacks, runnable); + stopTimingLoopIfNoCallbacksLocked(); } } @@ -377,14 +197,14 @@ public final class Choreographer { * * @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) { throw new IllegalArgumentException("runnable must not be null"); } synchronized (mLock) { - mOnDrawCallbacks = addCallbackLocked(mOnDrawCallbacks, runnable); + mDrawCallbacks = addCallbackLocked(mDrawCallbacks, runnable); scheduleDrawLocked(); } } @@ -396,15 +216,63 @@ public final class Choreographer { * * @param runnable The draw callback to remove. * - * @see #postOnDrawCallback + * @see #postDrawCallback */ - public void removeOnDrawCallback(Runnable runnable) { + public void removeDrawCallback(Runnable runnable) { if (runnable == null) { throw new IllegalArgumentException("runnable must not be null"); } synchronized (mLock) { - mOnDrawCallbacks = removeCallbackLocked(mOnDrawCallbacks, runnable); - stopTimingLoopIfNoListenersOrCallbacksLocked(); + mDrawCallbacks = removeCallbackLocked(mDrawCallbacks, runnable); + 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() { final long start; - final OnAnimateListener[] listeners; final Callback callbacks; synchronized (mLock) { if (!mAnimationScheduled) { @@ -433,15 +300,8 @@ public final class Choreographer { } mLastAnimationTime = start; - listeners = mOnAnimateListeners; - callbacks = mOnAnimateCallbacks; - mOnAnimateCallbacks = null; - } - - if (listeners != null) { - for (int i = 0; i < listeners.length; i++) { - listeners[i].onAnimate(); - } + callbacks = mAnimationCallbacks; + mAnimationCallbacks = null; } if (callbacks != null) { @@ -458,7 +318,6 @@ public final class Choreographer { void doDraw() { final long start; - final OnDrawListener[] listeners; final Callback callbacks; synchronized (mLock) { if (!mDrawScheduled) { @@ -473,15 +332,8 @@ public final class Choreographer { } mLastDrawTime = start; - listeners = mOnDrawListeners; - callbacks = mOnDrawCallbacks; - mOnDrawCallbacks = null; - } - - if (listeners != null) { - for (int i = 0; i < listeners.length; i++) { - listeners[i].onDraw(); - } + callbacks = mDrawCallbacks; + mDrawCallbacks = null; } if (callbacks != null) { @@ -520,9 +372,8 @@ public final class Choreographer { } } - private void stopTimingLoopIfNoListenersOrCallbacksLocked() { - if (mOnAnimateListeners == null && mOnDrawListeners == null - && mOnAnimateCallbacks == null && mOnDrawCallbacks == null) { + private void stopTimingLoopIfNoCallbacksLocked() { + if (mAnimationCallbacks == null && mDrawCallbacks == null) { if (DEBUG) { Log.d(TAG, "Stopping timing loop."); } @@ -627,26 +478,6 @@ public final class Choreographer { 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 { public FrameHandler(Looper looper) { super(looper); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 1930a5e..fbcb423 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -97,8 +97,7 @@ import java.util.List; */ @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"}) public final class ViewRootImpl extends Handler implements ViewParent, - View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks, - Choreographer.OnDrawListener { + View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks { private static final String TAG = "ViewRootImpl"; private static final boolean DBG = 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) { synchronized (this) { if (mView == null) { - mChoreographer.addOnDrawListener(this); - mView = view; mFallbackEventHandler.setView(view); mWindowAttributes.copyFrom(attrs); @@ -841,7 +838,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, public void scheduleTraversals() { if (!mTraversalScheduled) { mTraversalScheduled = true; - mChoreographer.scheduleDraw(); + scheduleFrame(); } } @@ -849,8 +846,21 @@ public final class ViewRootImpl extends Handler implements ViewParent, mTraversalScheduled = false; } - @Override - public void onDraw() { + void scheduleFrame() { + if (!mFrameScheduled) { + mChoreographer.postDrawCallback(mFrameRunnable); + mFrameScheduled = true; + } + } + + void unscheduleFrame() { + if (mFrameScheduled) { + mFrameScheduled = false; + mChoreographer.removeDrawCallback(mFrameRunnable); + } + } + + void doFrame() { if (mInputEventReceiver != null) { mInputEventReceiver.consumeBatchedInputEvents(); } @@ -2376,7 +2386,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, mInputChannel = null; } - mChoreographer.removeOnDrawListener(this); + unscheduleFrame(); } 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 { public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); @@ -3935,7 +3955,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, @Override public void onBatchedInputEventPending() { - mChoreographer.scheduleDraw(); + scheduleFrame(); } } WindowInputEventReceiver mInputEventReceiver; |
