Merge "Speculatively schedule input consumption" into klp-dev

This commit is contained in:
Michael Wright
2013-10-29 20:20:45 +00:00
committed by Android (Google) Code Review
3 changed files with 34 additions and 13 deletions

View File

@@ -48,7 +48,7 @@ public abstract class InputEventReceiver {
InputChannel inputChannel, MessageQueue messageQueue); InputChannel inputChannel, MessageQueue messageQueue);
private static native void nativeDispose(int receiverPtr); private static native void nativeDispose(int receiverPtr);
private static native void nativeFinishInputEvent(int receiverPtr, int seq, boolean handled); private static native void nativeFinishInputEvent(int receiverPtr, int seq, boolean handled);
private static native void nativeConsumeBatchedInputEvents(int receiverPtr, private static native boolean nativeConsumeBatchedInputEvents(int receiverPtr,
long frameTimeNanos); long frameTimeNanos);
/** /**
@@ -165,14 +165,17 @@ public abstract class InputEventReceiver {
* *
* @param frameTimeNanos The time in the {@link System#nanoTime()} time base * @param frameTimeNanos The time in the {@link System#nanoTime()} time base
* when the current display frame started rendering, or -1 if unknown. * when the current display frame started rendering, or -1 if unknown.
*
* @return Whether a batch was consumed
*/ */
public final void consumeBatchedInputEvents(long frameTimeNanos) { public final boolean consumeBatchedInputEvents(long frameTimeNanos) {
if (mReceiverPtr == 0) { if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to consume batched input events but the input event " Log.w(TAG, "Attempted to consume batched input events but the input event "
+ "receiver has already been disposed."); + "receiver has already been disposed.");
} else { } else {
nativeConsumeBatchedInputEvents(mReceiverPtr, frameTimeNanos); return nativeConsumeBatchedInputEvents(mReceiverPtr, frameTimeNanos);
} }
return false;
} }
// Called from native code. // Called from native code.

View File

@@ -5635,7 +5635,13 @@ public final class ViewRootImpl implements ViewParent,
if (mConsumeBatchedInputScheduled) { if (mConsumeBatchedInputScheduled) {
mConsumeBatchedInputScheduled = false; mConsumeBatchedInputScheduled = false;
if (mInputEventReceiver != null) { if (mInputEventReceiver != null) {
mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos); if (mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos)) {
// 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.
scheduleConsumeBatchedInput();
}
} }
doProcessInputEvents(); doProcessInputEvents();
} }

View File

@@ -56,7 +56,8 @@ public:
status_t initialize(); status_t initialize();
void dispose(); void dispose();
status_t finishInputEvent(uint32_t seq, bool handled); status_t finishInputEvent(uint32_t seq, bool handled);
status_t consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime); status_t consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime,
bool* outConsumedBatch);
protected: protected:
virtual ~NativeInputEventReceiver(); virtual ~NativeInputEventReceiver();
@@ -167,7 +168,7 @@ int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data)
if (events & ALOOPER_EVENT_INPUT) { if (events & ALOOPER_EVENT_INPUT) {
JNIEnv* env = AndroidRuntime::getJNIEnv(); JNIEnv* env = AndroidRuntime::getJNIEnv();
status_t status = consumeEvents(env, false /*consumeBatches*/, -1); status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback"); mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? 1 : 0; return status == OK || status == NO_MEMORY ? 1 : 0;
} }
@@ -214,7 +215,7 @@ int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data)
} }
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime) { bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
#if DEBUG_DISPATCH_CYCLE #if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.", ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.",
getInputChannelName(), consumeBatches ? "true" : "false", frameTime); getInputChannelName(), consumeBatches ? "true" : "false", frameTime);
@@ -223,6 +224,9 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
if (consumeBatches) { if (consumeBatches) {
mBatchedInputEventPending = false; mBatchedInputEventPending = false;
} }
if (outConsumedBatch) {
*outConsumedBatch = false;
}
ScopedLocalRef<jobject> receiverObj(env, NULL); ScopedLocalRef<jobject> receiverObj(env, NULL);
bool skipCallbacks = false; bool skipCallbacks = false;
@@ -285,13 +289,17 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
static_cast<KeyEvent*>(inputEvent)); static_cast<KeyEvent*>(inputEvent));
break; break;
case AINPUT_EVENT_TYPE_MOTION: case AINPUT_EVENT_TYPE_MOTION: {
#if DEBUG_DISPATCH_CYCLE #if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ Received motion event.", getInputChannelName()); ALOGD("channel '%s' ~ Received motion event.", getInputChannelName());
#endif #endif
inputEventObj = android_view_MotionEvent_obtainAsCopy(env, MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);
static_cast<MotionEvent*>(inputEvent)); if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) {
*outConsumedBatch = true;
}
inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
break; break;
}
default: default:
assert(false); // InputConsumer should prevent this from ever happening assert(false); // InputConsumer should prevent this from ever happening
@@ -370,16 +378,20 @@ static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr,
} }
} }
static void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr, static bool nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr,
jlong frameTimeNanos) { jlong frameTimeNanos) {
sp<NativeInputEventReceiver> receiver = sp<NativeInputEventReceiver> receiver =
reinterpret_cast<NativeInputEventReceiver*>(receiverPtr); reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos); bool consumedBatch;
status_t status = receiver->consumeEvents(env, true /*consumeBatches*/, frameTimeNanos,
&consumedBatch);
if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) { if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
String8 message; String8 message;
message.appendFormat("Failed to consume batched input event. status=%d", status); message.appendFormat("Failed to consume batched input event. status=%d", status);
jniThrowRuntimeException(env, message.string()); jniThrowRuntimeException(env, message.string());
return false;
} }
return consumedBatch;
} }
@@ -392,7 +404,7 @@ static JNINativeMethod gMethods[] = {
(void*)nativeDispose }, (void*)nativeDispose },
{ "nativeFinishInputEvent", "(IIZ)V", { "nativeFinishInputEvent", "(IIZ)V",
(void*)nativeFinishInputEvent }, (void*)nativeFinishInputEvent },
{ "nativeConsumeBatchedInputEvents", "(IJ)V", { "nativeConsumeBatchedInputEvents", "(IJ)Z",
(void*)nativeConsumeBatchedInputEvents }, (void*)nativeConsumeBatchedInputEvents },
}; };