Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -32957,6 +32957,7 @@ package android.view { method public void requestLayout(); method public boolean requestRectangleOnScreen(android.graphics.Rect); method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean); method public final void requestUnbufferedDispatch(android.view.MotionEvent); method public static int resolveSize(int, int); method public static int resolveSizeAndState(int, int, int); method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>); core/java/android/view/View.java +30 −0 Original line number Diff line number Diff line Loading @@ -9235,6 +9235,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mTouchDelegate; } /** * Request unbuffered dispatch of the given stream of MotionEvents to this View. * * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input * system not batch {@link MotionEvent}s but instead deliver them as soon as they're * available. This method should only be called for touch events. * * <p class="note">This api is not intended for most applications. Buffered dispatch * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent * streams will not improve your input latency. Side effects include: increased latency, * jittery scrolls and inability to take advantage of system resampling. Talk to your input * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for * you.</p> */ public final void requestUnbufferedDispatch(MotionEvent event) { final int action = event.getAction(); if (mAttachInfo == null || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE || !event.isTouchEvent()) { return; } mAttachInfo.mUnbufferedDispatchRequested = true; } /** * Set flags controlling behavior of this view. * Loading Loading @@ -19759,6 +19783,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ boolean mInTouchMode; /** * Indicates whether the view has requested unbuffered input dispatching for the current * event stream. */ boolean mUnbufferedDispatchRequested; /** * Indicates that ViewAncestor should trigger a global layout change * the next time it performs a traversal core/java/android/view/ViewRootImpl.java +55 −8 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ public final class ViewRootImpl implements ViewParent, QueuedInputEvent mPendingInputEventTail; int mPendingInputEventCount; boolean mProcessInputEventsScheduled; boolean mUnbufferedInputDispatch; String mPendingInputEventQueueLengthCounterName = "pq"; InputStage mFirstInputStage; Loading Loading @@ -1005,9 +1006,11 @@ public final class ViewRootImpl implements ViewParent, mTraversalBarrier = mHandler.getLooper().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); if (!mUnbufferedInputDispatch) { scheduleConsumeBatchedInput(); } } } void unscheduleTraversals() { if (mTraversalScheduled) { Loading Loading @@ -2604,7 +2607,7 @@ public final class ViewRootImpl implements ViewParent, } final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider(); final Rect bounds = mView.mAttachInfo.mTmpInvalRect; final Rect bounds = mAttachInfo.mTmpInvalRect; if (provider == null) { host.getBoundsOnScreen(bounds); } else if (mAccessibilityFocusedVirtualView != null) { Loading Loading @@ -3886,6 +3889,18 @@ public final class ViewRootImpl implements ViewParent, } } @Override protected void onDeliverToNext(QueuedInputEvent q) { if (mUnbufferedInputDispatch && q.mEvent instanceof MotionEvent && ((MotionEvent)q.mEvent).isTouchEvent() && isTerminalInputEvent(q.mEvent)) { mUnbufferedInputDispatch = false; scheduleConsumeBatchedInput(); } super.onDeliverToNext(q); } private int processKeyEvent(QueuedInputEvent q) { final KeyEvent event = (KeyEvent)q.mEvent; Loading Loading @@ -3998,10 +4013,15 @@ public final class ViewRootImpl implements ViewParent, private int processPointerEvent(QueuedInputEvent q) { final MotionEvent event = (MotionEvent)q.mEvent; if (mView.dispatchPointerEvent(event)) { return FINISH_HANDLED; mAttachInfo.mUnbufferedDispatchRequested = false; boolean handled = mView.dispatchPointerEvent(event); if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) { mUnbufferedInputDispatch = true; if (mConsumeBatchedInputScheduled) { scheduleConsumeBatchedInputImmediately(); } return FORWARD; } return handled ? FINISH_HANDLED : FORWARD; } private int processTrackballEvent(QueuedInputEvent q) { Loading Loading @@ -5266,6 +5286,8 @@ public final class ViewRootImpl implements ViewParent, writer.print(" mRemoved="); writer.println(mRemoved); writer.print(innerPrefix); writer.print("mConsumeBatchedInputScheduled="); writer.println(mConsumeBatchedInputScheduled); writer.print(innerPrefix); writer.print("mConsumeBatchedInputImmediatelyScheduled="); writer.println(mConsumeBatchedInputImmediatelyScheduled); writer.print(innerPrefix); writer.print("mPendingInputEventCount="); writer.println(mPendingInputEventCount); writer.print(innerPrefix); writer.print("mProcessInputEventsScheduled="); Loading Loading @@ -5676,6 +5698,7 @@ public final class ViewRootImpl implements ViewParent, private void finishInputEvent(QueuedInputEvent q) { Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "deliverInputEvent", q.mEvent.getSequenceNumber()); if (q.mReceiver != null) { boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0; q.mReceiver.finishInputEvent(q.mEvent, handled); Loading Loading @@ -5715,15 +5738,25 @@ public final class ViewRootImpl implements ViewParent, } } void scheduleConsumeBatchedInputImmediately() { if (!mConsumeBatchedInputImmediatelyScheduled) { unscheduleConsumeBatchedInput(); mConsumeBatchedInputImmediatelyScheduled = true; mHandler.post(mConsumeBatchedInputImmediatelyRunnable); } } void doConsumeBatchedInput(long frameTimeNanos) { if (mConsumeBatchedInputScheduled) { mConsumeBatchedInputScheduled = false; if (mInputEventReceiver != null) { if (mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos)) { if (mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos) && frameTimeNanos != -1) { // If we consumed a batch here, we want to go ahead and schedule the // consumption of batched input events on the next frame. Otherwise, we would // wait until we have more input events pending and might get starved by other // things occurring in the process. // things occurring in the process. If the frame time is -1, however, then // we're in a non-batching mode, so there's no need to schedule this. scheduleConsumeBatchedInput(); } } Loading Loading @@ -5751,8 +5784,12 @@ public final class ViewRootImpl implements ViewParent, @Override public void onBatchedInputEventPending() { if (mUnbufferedInputDispatch) { super.onBatchedInputEventPending(); } else { scheduleConsumeBatchedInput(); } } @Override public void dispose() { Loading @@ -5772,6 +5809,16 @@ public final class ViewRootImpl implements ViewParent, new ConsumeBatchedInputRunnable(); boolean mConsumeBatchedInputScheduled; final class ConsumeBatchedInputImmediatelyRunnable implements Runnable { @Override public void run() { doConsumeBatchedInput(-1); } } final ConsumeBatchedInputImmediatelyRunnable mConsumeBatchedInputImmediatelyRunnable = new ConsumeBatchedInputImmediatelyRunnable(); boolean mConsumeBatchedInputImmediatelyScheduled; final class InvalidateOnAnimationRunnable implements Runnable { private boolean mPosted; private final ArrayList<View> mViews = new ArrayList<View>(); Loading Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -32957,6 +32957,7 @@ package android.view { method public void requestLayout(); method public boolean requestRectangleOnScreen(android.graphics.Rect); method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean); method public final void requestUnbufferedDispatch(android.view.MotionEvent); method public static int resolveSize(int, int); method public static int resolveSizeAndState(int, int, int); method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
core/java/android/view/View.java +30 −0 Original line number Diff line number Diff line Loading @@ -9235,6 +9235,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return mTouchDelegate; } /** * Request unbuffered dispatch of the given stream of MotionEvents to this View. * * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input * system not batch {@link MotionEvent}s but instead deliver them as soon as they're * available. This method should only be called for touch events. * * <p class="note">This api is not intended for most applications. Buffered dispatch * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent * streams will not improve your input latency. Side effects include: increased latency, * jittery scrolls and inability to take advantage of system resampling. Talk to your input * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for * you.</p> */ public final void requestUnbufferedDispatch(MotionEvent event) { final int action = event.getAction(); if (mAttachInfo == null || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE || !event.isTouchEvent()) { return; } mAttachInfo.mUnbufferedDispatchRequested = true; } /** * Set flags controlling behavior of this view. * Loading Loading @@ -19759,6 +19783,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ boolean mInTouchMode; /** * Indicates whether the view has requested unbuffered input dispatching for the current * event stream. */ boolean mUnbufferedDispatchRequested; /** * Indicates that ViewAncestor should trigger a global layout change * the next time it performs a traversal
core/java/android/view/ViewRootImpl.java +55 −8 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ public final class ViewRootImpl implements ViewParent, QueuedInputEvent mPendingInputEventTail; int mPendingInputEventCount; boolean mProcessInputEventsScheduled; boolean mUnbufferedInputDispatch; String mPendingInputEventQueueLengthCounterName = "pq"; InputStage mFirstInputStage; Loading Loading @@ -1005,9 +1006,11 @@ public final class ViewRootImpl implements ViewParent, mTraversalBarrier = mHandler.getLooper().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); if (!mUnbufferedInputDispatch) { scheduleConsumeBatchedInput(); } } } void unscheduleTraversals() { if (mTraversalScheduled) { Loading Loading @@ -2604,7 +2607,7 @@ public final class ViewRootImpl implements ViewParent, } final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider(); final Rect bounds = mView.mAttachInfo.mTmpInvalRect; final Rect bounds = mAttachInfo.mTmpInvalRect; if (provider == null) { host.getBoundsOnScreen(bounds); } else if (mAccessibilityFocusedVirtualView != null) { Loading Loading @@ -3886,6 +3889,18 @@ public final class ViewRootImpl implements ViewParent, } } @Override protected void onDeliverToNext(QueuedInputEvent q) { if (mUnbufferedInputDispatch && q.mEvent instanceof MotionEvent && ((MotionEvent)q.mEvent).isTouchEvent() && isTerminalInputEvent(q.mEvent)) { mUnbufferedInputDispatch = false; scheduleConsumeBatchedInput(); } super.onDeliverToNext(q); } private int processKeyEvent(QueuedInputEvent q) { final KeyEvent event = (KeyEvent)q.mEvent; Loading Loading @@ -3998,10 +4013,15 @@ public final class ViewRootImpl implements ViewParent, private int processPointerEvent(QueuedInputEvent q) { final MotionEvent event = (MotionEvent)q.mEvent; if (mView.dispatchPointerEvent(event)) { return FINISH_HANDLED; mAttachInfo.mUnbufferedDispatchRequested = false; boolean handled = mView.dispatchPointerEvent(event); if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) { mUnbufferedInputDispatch = true; if (mConsumeBatchedInputScheduled) { scheduleConsumeBatchedInputImmediately(); } return FORWARD; } return handled ? FINISH_HANDLED : FORWARD; } private int processTrackballEvent(QueuedInputEvent q) { Loading Loading @@ -5266,6 +5286,8 @@ public final class ViewRootImpl implements ViewParent, writer.print(" mRemoved="); writer.println(mRemoved); writer.print(innerPrefix); writer.print("mConsumeBatchedInputScheduled="); writer.println(mConsumeBatchedInputScheduled); writer.print(innerPrefix); writer.print("mConsumeBatchedInputImmediatelyScheduled="); writer.println(mConsumeBatchedInputImmediatelyScheduled); writer.print(innerPrefix); writer.print("mPendingInputEventCount="); writer.println(mPendingInputEventCount); writer.print(innerPrefix); writer.print("mProcessInputEventsScheduled="); Loading Loading @@ -5676,6 +5698,7 @@ public final class ViewRootImpl implements ViewParent, private void finishInputEvent(QueuedInputEvent q) { Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "deliverInputEvent", q.mEvent.getSequenceNumber()); if (q.mReceiver != null) { boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0; q.mReceiver.finishInputEvent(q.mEvent, handled); Loading Loading @@ -5715,15 +5738,25 @@ public final class ViewRootImpl implements ViewParent, } } void scheduleConsumeBatchedInputImmediately() { if (!mConsumeBatchedInputImmediatelyScheduled) { unscheduleConsumeBatchedInput(); mConsumeBatchedInputImmediatelyScheduled = true; mHandler.post(mConsumeBatchedInputImmediatelyRunnable); } } void doConsumeBatchedInput(long frameTimeNanos) { if (mConsumeBatchedInputScheduled) { mConsumeBatchedInputScheduled = false; if (mInputEventReceiver != null) { if (mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos)) { if (mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos) && frameTimeNanos != -1) { // If we consumed a batch here, we want to go ahead and schedule the // consumption of batched input events on the next frame. Otherwise, we would // wait until we have more input events pending and might get starved by other // things occurring in the process. // things occurring in the process. If the frame time is -1, however, then // we're in a non-batching mode, so there's no need to schedule this. scheduleConsumeBatchedInput(); } } Loading Loading @@ -5751,8 +5784,12 @@ public final class ViewRootImpl implements ViewParent, @Override public void onBatchedInputEventPending() { if (mUnbufferedInputDispatch) { super.onBatchedInputEventPending(); } else { scheduleConsumeBatchedInput(); } } @Override public void dispose() { Loading @@ -5772,6 +5809,16 @@ public final class ViewRootImpl implements ViewParent, new ConsumeBatchedInputRunnable(); boolean mConsumeBatchedInputScheduled; final class ConsumeBatchedInputImmediatelyRunnable implements Runnable { @Override public void run() { doConsumeBatchedInput(-1); } } final ConsumeBatchedInputImmediatelyRunnable mConsumeBatchedInputImmediatelyRunnable = new ConsumeBatchedInputImmediatelyRunnable(); boolean mConsumeBatchedInputImmediatelyScheduled; final class InvalidateOnAnimationRunnable implements Runnable { private boolean mPosted; private final ArrayList<View> mViews = new ArrayList<View>(); Loading