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

Commit 2a89b08e authored by Michael Wright's avatar Michael Wright Committed by Android (Google) Code Review
Browse files

Merge "Add ability to request unbuffered dispatching."

parents 4e843738 9d744c73
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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>);
+30 −0
Original line number Diff line number Diff line
@@ -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.
     *
@@ -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
+55 −8
Original line number Diff line number Diff line
@@ -230,6 +230,7 @@ public final class ViewRootImpl implements ViewParent,
    QueuedInputEvent mPendingInputEventTail;
    int mPendingInputEventCount;
    boolean mProcessInputEventsScheduled;
    boolean mUnbufferedInputDispatch;
    String mPendingInputEventQueueLengthCounterName = "pq";

    InputStage mFirstInputStage;
@@ -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) {
@@ -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) {
@@ -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;

@@ -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) {
@@ -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=");
@@ -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);
@@ -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();
                }
            }
@@ -5751,8 +5784,12 @@ public final class ViewRootImpl implements ViewParent,

        @Override
        public void onBatchedInputEventPending() {
            if (mUnbufferedInputDispatch) {
                super.onBatchedInputEventPending();
            } else {
                scheduleConsumeBatchedInput();
            }
        }

        @Override
        public void dispose() {
@@ -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>();