From 423346e7e295b61a699691e9f7690e3f228d7e35 Mon Sep 17 00:00:00 2001 From: Arthur Hung Date: Thu, 27 Feb 2020 21:56:11 +0800 Subject: [PATCH] Pass source to dispatchBatchedInputEventPending (1/2) The API requestUnbufferedDispatch allow View could receive the event in unbuffered way. But doing processUnbufferedRequest in onInputEvent is too late for the first event. Instead, we should pass the source of the input event up to onBatchedInputEventPending, and then we can use that to determine whether we could consume event immediately or not. Bug: 149715123 Test: atest ViewUnbufferedTest Change-Id: I4344a99de77d3758cc7d1df155394c89fa828f2e --- .../view/BatchedInputEventReceiver.java | 2 +- .../java/android/view/InputEventReceiver.java | 10 +-- core/java/android/view/ViewRootImpl.java | 32 ++++------ core/jni/android_view_InputEventReceiver.cpp | 64 ++++++++++--------- 4 files changed, 48 insertions(+), 60 deletions(-) diff --git a/core/java/android/view/BatchedInputEventReceiver.java b/core/java/android/view/BatchedInputEventReceiver.java index 95b2c7019dbc8..30e3ec1350658 100644 --- a/core/java/android/view/BatchedInputEventReceiver.java +++ b/core/java/android/view/BatchedInputEventReceiver.java @@ -35,7 +35,7 @@ public class BatchedInputEventReceiver extends InputEventReceiver { } @Override - public void onBatchedInputEventPending() { + public void onBatchedInputEventPending(int source) { scheduleBatchedInput(); } diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java index 7986ceb988dbe..25a4108c612cf 100644 --- a/core/java/android/view/InputEventReceiver.java +++ b/core/java/android/view/InputEventReceiver.java @@ -147,8 +147,9 @@ public abstract class InputEventReceiver { * samples until the recipient calls {@link #consumeBatchedInputEvents} or * an event is received that ends the batch and causes it to be consumed * immediately (such as a pointer up event). + * @param source The source of the batched event. */ - public void onBatchedInputEventPending() { + public void onBatchedInputEventPending(int source) { consumeBatchedInputEvents(-1); } @@ -219,13 +220,6 @@ public abstract class InputEventReceiver { onInputEvent(event); } - // Called from native code. - @SuppressWarnings("unused") - @UnsupportedAppUsage - private void dispatchBatchedInputEventPending() { - onBatchedInputEventPending(); - } - /** * Factory for InputEventReceiver */ diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index dd34bcb018b93..95149deb41f65 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -504,7 +504,6 @@ public final class ViewRootImpl implements ViewParent, int mPendingInputEventCount; boolean mProcessInputEventsScheduled; boolean mUnbufferedInputDispatch; - boolean mUnbufferedInputDispatchBySource; @InputSourceClass int mUnbufferedInputSource = SOURCE_CLASS_NONE; @@ -1872,9 +1871,6 @@ public final class ViewRootImpl implements ViewParent, mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); - if (!mUnbufferedInputDispatch && !mUnbufferedInputDispatchBySource) { - scheduleConsumeBatchedInput(); - } notifyRendererOfFramePending(); pokeDrawLockIfNeeded(); } @@ -8147,7 +8143,6 @@ public final class ViewRootImpl implements ViewParent, @Override public void onInputEvent(InputEvent event) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "processInputEventForCompatibility"); - processUnbufferedRequest(event); List processedEvents; try { processedEvents = @@ -8172,12 +8167,18 @@ public final class ViewRootImpl implements ViewParent, } @Override - public void onBatchedInputEventPending() { - if (mUnbufferedInputDispatch || mUnbufferedInputDispatchBySource) { - super.onBatchedInputEventPending(); - } else { - scheduleConsumeBatchedInput(); + public void onBatchedInputEventPending(int source) { + final boolean unbuffered = mUnbufferedInputDispatch + || (source & mUnbufferedInputSource) != SOURCE_CLASS_NONE; + if (unbuffered) { + if (mConsumeBatchedInputScheduled) { + unscheduleConsumeBatchedInput(); + } + // Consume event immediately if unbuffered input dispatch has been requested. + consumeBatchedInputEvents(-1); + return; } + scheduleConsumeBatchedInput(); } @Override @@ -8190,17 +8191,6 @@ public final class ViewRootImpl implements ViewParent, unscheduleConsumeBatchedInput(); super.dispose(); } - - private void processUnbufferedRequest(InputEvent event) { - if (!(event instanceof MotionEvent)) { - return; - } - mUnbufferedInputDispatchBySource = - (event.getSource() & mUnbufferedInputSource) != SOURCE_CLASS_NONE; - if (mUnbufferedInputDispatchBySource && mConsumeBatchedInputScheduled) { - scheduleConsumeBatchedInputImmediately(); - } - } } WindowInputEventReceiver mInputEventReceiver; diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index 649e5d2f49fe7..cc94d6ff5d673 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -49,7 +49,7 @@ static struct { jmethodID dispatchInputEvent; jmethodID onFocusEvent; - jmethodID dispatchBatchedInputEventPending; + jmethodID onBatchedInputEventPending; } gInputEventReceiverClassInfo; @@ -242,37 +242,40 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, status_t status = mInputConsumer.consume(&mInputEventFactory, consumeBatches, frameTime, &seq, &inputEvent); - if (status) { - if (status == WOULD_BLOCK) { - if (!skipCallbacks && !mBatchedInputEventPending - && mInputConsumer.hasPendingBatch()) { - // There is a pending batch. Come back later. - if (!receiverObj.get()) { - receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal)); - if (!receiverObj.get()) { - ALOGW("channel '%s' ~ Receiver object was finalized " - "without being disposed.", getInputChannelName().c_str()); - return DEAD_OBJECT; - } - } + if (status != OK && status != WOULD_BLOCK) { + ALOGE("channel '%s' ~ Failed to consume input event. status=%d", + getInputChannelName().c_str(), status); + return status; + } - mBatchedInputEventPending = true; - if (kDebugDispatchCycle) { - ALOGD("channel '%s' ~ Dispatching batched input event pending notification.", - getInputChannelName().c_str()); - } - env->CallVoidMethod(receiverObj.get(), - gInputEventReceiverClassInfo.dispatchBatchedInputEventPending); - if (env->ExceptionCheck()) { - ALOGE("Exception dispatching batched input events."); - mBatchedInputEventPending = false; // try again later + if (status == WOULD_BLOCK) { + if (!skipCallbacks && !mBatchedInputEventPending && mInputConsumer.hasPendingBatch()) { + // There is a pending batch. Come back later. + if (!receiverObj.get()) { + receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal)); + if (!receiverObj.get()) { + ALOGW("channel '%s' ~ Receiver object was finalized " + "without being disposed.", + getInputChannelName().c_str()); + return DEAD_OBJECT; } } - return OK; + + mBatchedInputEventPending = true; + if (kDebugDispatchCycle) { + ALOGD("channel '%s' ~ Dispatching batched input event pending notification.", + getInputChannelName().c_str()); + } + + env->CallVoidMethod(receiverObj.get(), + gInputEventReceiverClassInfo.onBatchedInputEventPending, + mInputConsumer.getPendingBatchSource()); + if (env->ExceptionCheck()) { + ALOGE("Exception dispatching batched input events."); + mBatchedInputEventPending = false; // try again later + } } - ALOGE("channel '%s' ~ Failed to consume input event. status=%d", - getInputChannelName().c_str(), status); - return status; + return OK; } assert(inputEvent); @@ -441,8 +444,9 @@ int register_android_view_InputEventReceiver(JNIEnv* env) { "dispatchInputEvent", "(ILandroid/view/InputEvent;)V"); gInputEventReceiverClassInfo.onFocusEvent = GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onFocusEvent", "(ZZ)V"); - gInputEventReceiverClassInfo.dispatchBatchedInputEventPending = GetMethodIDOrDie(env, - gInputEventReceiverClassInfo.clazz, "dispatchBatchedInputEventPending", "()V"); + gInputEventReceiverClassInfo.onBatchedInputEventPending = + GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onBatchedInputEventPending", + "(I)V"); return res; }