Implement batching of input events on the consumer side.
To support this feature, the input dispatcher now allows input
events to be acknowledged out-of-order. As a result, the
consumer can choose to defer handling an input event from one
device (because it is building a big batch) while continuing
to handle input events from other devices.
The InputEventReceiver now sends a notification when a batch
is pending. The ViewRoot handles this notification by scheduling
a draw on the next sync. When the draw happens, the InputEventReceiver
is instructed to consume all pending batched input events, the
input event queue is fully processed (as much as possible),
and then the ViewRoot performs traversals as usual.
With these changes in place, the input dispatch latency is
consistently less than one frame as long as the application itself
isn't stalled. Input events are delivered to the application
as soon as possible and are handled as soon as possible. In practice,
it is no longer possible for an application to build up a huge
backlog of touch events.
This is part of a series of changes to improve input system pipelining.
Bug: 5963420
Change-Id: I42c01117eca78f12d66d49a736c1c122346ccd1d
diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
index a0ee94b..3303053 100644
--- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp
@@ -69,6 +69,7 @@
void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() {
status_t status;
+ const uint32_t seq = 15;
const int32_t deviceId = 1;
const int32_t source = AINPUT_SOURCE_KEYBOARD;
const int32_t action = AKEY_EVENT_ACTION_DOWN;
@@ -80,13 +81,14 @@
const nsecs_t downTime = 3;
const nsecs_t eventTime = 4;
- status = mPublisher->publishKeyEvent(deviceId, source, action, flags,
+ status = mPublisher->publishKeyEvent(seq, deviceId, source, action, flags,
keyCode, scanCode, metaState, repeatCount, downTime, eventTime);
ASSERT_EQ(OK, status)
<< "publisher publishKeyEvent should return OK";
+ uint32_t consumeSeq;
InputEvent* event;
- status = mConsumer->consume(& mEventFactory, & event);
+ status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, &consumeSeq, &event);
ASSERT_EQ(OK, status)
<< "consumer consume should return OK";
@@ -96,6 +98,7 @@
<< "consumer should have returned a key event";
KeyEvent* keyEvent = static_cast<KeyEvent*>(event);
+ EXPECT_EQ(seq, consumeSeq);
EXPECT_EQ(deviceId, keyEvent->getDeviceId());
EXPECT_EQ(source, keyEvent->getSource());
EXPECT_EQ(action, keyEvent->getAction());
@@ -107,14 +110,17 @@
EXPECT_EQ(downTime, keyEvent->getDownTime());
EXPECT_EQ(eventTime, keyEvent->getEventTime());
- status = mConsumer->sendFinishedSignal(true);
+ status = mConsumer->sendFinishedSignal(seq, true);
ASSERT_EQ(OK, status)
<< "consumer sendFinishedSignal should return OK";
+ uint32_t finishedSeq = 0;
bool handled = false;
- status = mPublisher->receiveFinishedSignal(&handled);
+ status = mPublisher->receiveFinishedSignal(&finishedSeq, &handled);
ASSERT_EQ(OK, status)
<< "publisher receiveFinishedSignal should return OK";
+ ASSERT_EQ(seq, finishedSeq)
+ << "publisher receiveFinishedSignal should have returned the original sequence number";
ASSERT_TRUE(handled)
<< "publisher receiveFinishedSignal should have set handled to consumer's reply";
}
@@ -122,6 +128,7 @@
void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() {
status_t status;
+ const uint32_t seq = 15;
const int32_t deviceId = 1;
const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
const int32_t action = AMOTION_EVENT_ACTION_MOVE;
@@ -155,15 +162,16 @@
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
}
- status = mPublisher->publishMotionEvent(deviceId, source, action, flags, edgeFlags,
+ status = mPublisher->publishMotionEvent(seq, deviceId, source, action, flags, edgeFlags,
metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision,
downTime, eventTime, pointerCount,
pointerProperties, pointerCoords);
ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK";
+ uint32_t consumeSeq;
InputEvent* event;
- status = mConsumer->consume(& mEventFactory, & event);
+ status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, &consumeSeq, &event);
ASSERT_EQ(OK, status)
<< "consumer consume should return OK";
@@ -173,6 +181,7 @@
<< "consumer should have returned a motion event";
MotionEvent* motionEvent = static_cast<MotionEvent*>(event);
+ EXPECT_EQ(seq, consumeSeq);
EXPECT_EQ(deviceId, motionEvent->getDeviceId());
EXPECT_EQ(source, motionEvent->getSource());
EXPECT_EQ(action, motionEvent->getAction());
@@ -216,14 +225,17 @@
motionEvent->getOrientation(i));
}
- status = mConsumer->sendFinishedSignal(false);
+ status = mConsumer->sendFinishedSignal(seq, false);
ASSERT_EQ(OK, status)
<< "consumer sendFinishedSignal should return OK";
+ uint32_t finishedSeq = 0;
bool handled = true;
- status = mPublisher->receiveFinishedSignal(&handled);
+ status = mPublisher->receiveFinishedSignal(&finishedSeq, &handled);
ASSERT_EQ(OK, status)
<< "publisher receiveFinishedSignal should return OK";
+ ASSERT_EQ(seq, finishedSeq)
+ << "publisher receiveFinishedSignal should have returned the original sequence number";
ASSERT_FALSE(handled)
<< "publisher receiveFinishedSignal should have set handled to consumer's reply";
}
@@ -242,7 +254,7 @@
PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
@@ -258,7 +270,7 @@
pointerCoords[i].clear();
}
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";