diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/view/TextureView.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 48 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 104 | ||||
| -rw-r--r-- | core/java/android/widget/ProgressBar.java | 13 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 2 |
5 files changed, 152 insertions, 17 deletions
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 74916f0..fc02cc1 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -334,7 +334,7 @@ public class TextureView extends View { synchronized (mLock) { mUpdateLayer = true; } - postInvalidateDelayed(0); + postInvalidate(); } }; mSurface.setOnFrameAvailableListener(mUpdateListener); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index f7dc73c..6ac27a7 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8881,6 +8881,54 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } /** + * <p>Cause an invalidate to happen on the next animation time step, typically the + * next display frame.</p> + * + * <p>This method can be invoked from outside of the UI thread + * only when this View is attached to a window.</p> + * + * @hide + */ + public void postInvalidateOnAnimation() { + // We try only with the AttachInfo because there's no point in invalidating + // if we are not attached to our window + final AttachInfo attachInfo = mAttachInfo; + if (attachInfo != null) { + attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this); + } + } + + /** + * <p>Cause an invalidate of the specified area to happen on the next animation + * time step, typically the next display frame.</p> + * + * <p>This method can be invoked from outside of the UI thread + * only when this View is attached to a window.</p> + * + * @param left The left coordinate of the rectangle to invalidate. + * @param top The top coordinate of the rectangle to invalidate. + * @param right The right coordinate of the rectangle to invalidate. + * @param bottom The bottom coordinate of the rectangle to invalidate. + * + * @hide + */ + public void postInvalidateOnAnimation(int left, int top, int right, int bottom) { + // We try only with the AttachInfo because there's no point in invalidating + // if we are not attached to our window + final AttachInfo attachInfo = mAttachInfo; + if (attachInfo != null) { + final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire(); + info.target = this; + info.left = left; + info.top = top; + info.right = right; + info.bottom = bottom; + + attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info); + } + } + + /** * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. * This event is sent at most once every * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}. diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e0d0763..9e734a0 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3992,21 +3992,117 @@ public final class ViewRootImpl implements ViewParent, } WindowInputEventReceiver mInputEventReceiver; + final class InvalidateOnAnimationRunnable implements Runnable { + private boolean mPosted; + private ArrayList<View> mViews = new ArrayList<View>(); + private ArrayList<AttachInfo.InvalidateInfo> mViewRects = + new ArrayList<AttachInfo.InvalidateInfo>(); + private View[] mTempViews; + private AttachInfo.InvalidateInfo[] mTempViewRects; + + public void addView(View view) { + synchronized (this) { + mViews.add(view); + postIfNeededLocked(); + } + } + + public void addViewRect(AttachInfo.InvalidateInfo info) { + synchronized (this) { + mViewRects.add(info); + postIfNeededLocked(); + } + } + + public void removeView(View view) { + synchronized (this) { + mViews.remove(view); + + for (int i = mViewRects.size(); i-- > 0; ) { + AttachInfo.InvalidateInfo info = mViewRects.get(i); + if (info.target == view) { + mViewRects.remove(i); + info.release(); + } + } + + if (mPosted && mViews.isEmpty() && mViewRects.isEmpty()) { + mChoreographer.removeAnimationCallback(this); + mPosted = false; + } + } + } + + @Override + public void run() { + final int viewCount; + final int viewRectCount; + synchronized (this) { + mPosted = false; + + viewCount = mViews.size(); + if (viewCount != 0) { + mTempViews = mViews.toArray(mTempViews != null + ? mTempViews : new View[viewCount]); + mViews.clear(); + } + + viewRectCount = mViewRects.size(); + if (viewRectCount != 0) { + mTempViewRects = mViewRects.toArray(mTempViewRects != null + ? mTempViewRects : new AttachInfo.InvalidateInfo[viewRectCount]); + mViewRects.clear(); + } + } + + for (int i = 0; i < viewCount; i++) { + mTempViews[i].invalidate(); + } + + for (int i = 0; i < viewRectCount; i++) { + final View.AttachInfo.InvalidateInfo info = mTempViewRects[i]; + info.target.invalidate(info.left, info.top, info.right, info.bottom); + info.release(); + } + } + + private void postIfNeededLocked() { + if (!mPosted) { + mChoreographer.postAnimationCallback(this); + mPosted = true; + } + } + } + final InvalidateOnAnimationRunnable mInvalidateOnAnimationRunnable = + new InvalidateOnAnimationRunnable(); + public void dispatchInvalidateDelayed(View view, long delayMilliseconds) { Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view); mHandler.sendMessageDelayed(msg, delayMilliseconds); } - public void cancelInvalidate(View view) { - mHandler.removeMessages(MSG_INVALIDATE, view); - } - public void dispatchInvalidateRectDelayed(AttachInfo.InvalidateInfo info, long delayMilliseconds) { final Message msg = mHandler.obtainMessage(MSG_INVALIDATE_RECT, info); mHandler.sendMessageDelayed(msg, delayMilliseconds); } + public void dispatchInvalidateOnAnimation(View view) { + mInvalidateOnAnimationRunnable.addView(view); + } + + public void dispatchInvalidateRectOnAnimation(AttachInfo.InvalidateInfo info) { + mInvalidateOnAnimationRunnable.addViewRect(info); + } + + public void cancelInvalidate(View view) { + mHandler.removeMessages(MSG_INVALIDATE, view); + // fixme: might leak the AttachInfo.InvalidateInfo objects instead of returning + // them to the pool + mHandler.removeMessages(MSG_INVALIDATE_RECT, view); + mInvalidateOnAnimationRunnable.removeView(view); + } + public void dispatchKey(KeyEvent event) { Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY, event); msg.setAsynchronous(true); diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index ace3f60..e298acb 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -39,6 +39,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.util.AttributeSet; +import android.view.Choreographer; import android.view.Gravity; import android.view.RemotableViewMethod; import android.view.View; @@ -189,7 +190,6 @@ import android.widget.RemoteViews.RemoteView; @RemoteView public class ProgressBar extends View { private static final int MAX_LEVEL = 10000; - private static final int ANIMATION_RESOLUTION = 200; private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200; int mMinWidth; @@ -216,12 +216,9 @@ public class ProgressBar extends View { private RefreshProgressRunnable mRefreshProgressRunnable; private long mUiThreadId; private boolean mShouldStartAnimationDrawable; - private long mLastDrawTime; private boolean mInDrawing; - private int mAnimationResolution; - private AccessibilityEventSender mAccessibilityEventSender; /** @@ -299,9 +296,6 @@ public class ProgressBar extends View { setIndeterminate(mOnlyIndeterminate || a.getBoolean( R.styleable.ProgressBar_indeterminate, mIndeterminate)); - mAnimationResolution = a.getInteger(R.styleable.ProgressBar_animationResolution, - ANIMATION_RESOLUTION); - a.recycle(); } @@ -988,10 +982,7 @@ public class ProgressBar extends View { } finally { mInDrawing = false; } - if (SystemClock.uptimeMillis() - mLastDrawTime >= mAnimationResolution) { - mLastDrawTime = SystemClock.uptimeMillis(); - postInvalidateDelayed(mAnimationResolution); - } + postInvalidateOnAnimation(); } d.draw(canvas); canvas.restore(); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 56a0d1e..e0b6fdc 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -9175,7 +9175,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int top = getExtendedPaddingTop() + getVerticalOffset(true); if (delayed) { - TextView.this.postInvalidateDelayed(16, // 60 Hz update + TextView.this.postInvalidateOnAnimation( left + (int) TEMP_RECTF.left, top + (int) TEMP_RECTF.top, left + (int) TEMP_RECTF.right, top + (int) TEMP_RECTF.bottom); } else { |
