Move drag event to InputDispatcher (1/n)
This CL adds the ability to send a DRAG event through the
InputChannel, and adds the appropriate processing logic to
InputPublisher and InputConsumer.
Bug: 158242495
Test: atest libinput_tests InputPublisherAndConsumerTest
Change-Id: I7aead341a9851facf654024c476bd6d7eaae4590
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 0a00d68..5600eb3 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -92,6 +92,9 @@
case AINPUT_EVENT_TYPE_CAPTURE: {
return "CAPTURE";
}
+ case AINPUT_EVENT_TYPE_DRAG: {
+ return "DRAG";
+ }
}
return "UNKNOWN";
}
@@ -770,6 +773,23 @@
mPointerCaptureEnabled = from.mPointerCaptureEnabled;
}
+// --- DragEvent ---
+
+void DragEvent::initialize(int32_t id, float x, float y, bool isExiting) {
+ InputEvent::initialize(id, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN,
+ ADISPLAY_ID_NONE, INVALID_HMAC);
+ mIsExiting = isExiting;
+ mX = x;
+ mY = y;
+}
+
+void DragEvent::initialize(const DragEvent& from) {
+ InputEvent::initialize(from);
+ mIsExiting = from.mIsExiting;
+ mX = from.mX;
+ mY = from.mY;
+}
+
// --- PooledInputEventFactory ---
PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
@@ -815,6 +835,15 @@
return event;
}
+DragEvent* PooledInputEventFactory::createDragEvent() {
+ if (mDragEventPool.empty()) {
+ return new DragEvent();
+ }
+ DragEvent* event = mDragEventPool.front().release();
+ mDragEventPool.pop();
+ return event;
+}
+
void PooledInputEventFactory::recycle(InputEvent* event) {
switch (event->getType()) {
case AINPUT_EVENT_TYPE_KEY:
@@ -842,6 +871,12 @@
return;
}
break;
+ case AINPUT_EVENT_TYPE_DRAG:
+ if (mDragEventPool.size() < mMaxPoolSize) {
+ mDragEventPool.push(std::unique_ptr<DragEvent>(static_cast<DragEvent*>(event)));
+ return;
+ }
+ break;
}
delete event;
}
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index ee2daec..6ef0173 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -108,6 +108,8 @@
return true;
case Type::CAPTURE:
return true;
+ case Type::DRAG:
+ return true;
}
}
return false;
@@ -125,6 +127,8 @@
return sizeof(Header) + body.focus.size();
case Type::CAPTURE:
return sizeof(Header) + body.capture.size();
+ case Type::DRAG:
+ return sizeof(Header) + body.drag.size();
}
return sizeof(Header);
}
@@ -249,6 +253,13 @@
msg->body.capture.pointerCaptureEnabled = body.capture.pointerCaptureEnabled;
break;
}
+ case InputMessage::Type::DRAG: {
+ msg->body.drag.eventId = body.drag.eventId;
+ msg->body.drag.x = body.drag.x;
+ msg->body.drag.y = body.drag.y;
+ msg->body.drag.isExiting = body.drag.isExiting;
+ break;
+ }
}
}
@@ -599,6 +610,25 @@
return mChannel->sendMessage(&msg);
}
+status_t InputPublisher::publishDragEvent(uint32_t seq, int32_t eventId, float x, float y,
+ bool isExiting) {
+ if (ATRACE_ENABLED()) {
+ std::string message =
+ StringPrintf("publishDragEvent(inputChannel=%s, x=%f, y=%f, isExiting=%s)",
+ mChannel->getName().c_str(), x, y, toString(isExiting));
+ ATRACE_NAME(message.c_str());
+ }
+
+ InputMessage msg;
+ msg.header.type = InputMessage::Type::DRAG;
+ msg.header.seq = seq;
+ msg.body.drag.eventId = eventId;
+ msg.body.drag.isExiting = isExiting;
+ msg.body.drag.x = x;
+ msg.body.drag.y = y;
+ return mChannel->sendMessage(&msg);
+}
+
status_t InputPublisher::receiveFinishedSignal(
const std::function<void(uint32_t seq, bool handled, nsecs_t consumeTime)>& callback) {
if (DEBUG_TRANSPORT_ACTIONS) {
@@ -779,6 +809,16 @@
*outEvent = captureEvent;
break;
}
+
+ case InputMessage::Type::DRAG: {
+ DragEvent* dragEvent = factory->createDragEvent();
+ if (!dragEvent) return NO_MEMORY;
+
+ initializeDragEvent(dragEvent, &mMsg);
+ *outSeq = mMsg.header.seq;
+ *outEvent = dragEvent;
+ break;
+ }
}
}
return OK;
@@ -1236,6 +1276,11 @@
event->initialize(msg->body.capture.eventId, msg->body.capture.pointerCaptureEnabled);
}
+void InputConsumer::initializeDragEvent(DragEvent* event, const InputMessage* msg) {
+ event->initialize(msg->body.drag.eventId, msg->body.drag.x, msg->body.drag.y,
+ msg->body.drag.isExiting);
+}
+
void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage* msg) {
uint32_t pointerCount = msg->body.motion.pointerCount;
PointerProperties pointerProperties[pointerCount];
@@ -1346,6 +1391,12 @@
.pointerCaptureEnabled));
break;
}
+ case InputMessage::Type::DRAG: {
+ out += android::base::StringPrintf("x=%.1f y=%.1f, isExiting=%s",
+ msg.body.drag.x, msg.body.drag.y,
+ toString(msg.body.drag.isExiting));
+ break;
+ }
}
out += "\n";
}
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index e7e566d..b5ed8d7 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -52,6 +52,7 @@
void PublishAndConsumeMotionEvent();
void PublishAndConsumeFocusEvent();
void PublishAndConsumeCaptureEvent();
+ void PublishAndConsumeDragEvent();
};
TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) {
@@ -301,7 +302,7 @@
const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
status = mPublisher->publishFocusEvent(seq, eventId, hasFocus, inTouchMode);
- ASSERT_EQ(OK, status) << "publisher publishKeyEvent should return OK";
+ ASSERT_EQ(OK, status) << "publisher publishFocusEvent should return OK";
uint32_t consumeSeq;
InputEvent* event;
@@ -349,7 +350,7 @@
const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
status = mPublisher->publishCaptureEvent(seq, eventId, captureEnabled);
- ASSERT_EQ(OK, status) << "publisher publishKeyEvent should return OK";
+ ASSERT_EQ(OK, status) << "publisher publishCaptureEvent should return OK";
uint32_t consumeSeq;
InputEvent* event;
@@ -387,6 +388,57 @@
<< "finished signal's consume time should be greater than publish time";
}
+void InputPublisherAndConsumerTest::PublishAndConsumeDragEvent() {
+ status_t status;
+
+ constexpr uint32_t seq = 15;
+ int32_t eventId = InputEvent::nextId();
+ constexpr bool isExiting = false;
+ constexpr float x = 10;
+ constexpr float y = 15;
+ const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ status = mPublisher->publishDragEvent(seq, eventId, x, y, isExiting);
+ ASSERT_EQ(OK, status) << "publisher publishDragEvent should return OK";
+
+ uint32_t consumeSeq;
+ InputEvent* event;
+ status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
+ ASSERT_EQ(OK, status) << "consumer consume should return OK";
+
+ ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event";
+ ASSERT_EQ(AINPUT_EVENT_TYPE_DRAG, event->getType())
+ << "consumer should have returned a drag event";
+
+ DragEvent* dragEvent = static_cast<DragEvent*>(event);
+ EXPECT_EQ(seq, consumeSeq);
+ EXPECT_EQ(eventId, dragEvent->getId());
+ EXPECT_EQ(isExiting, dragEvent->isExiting());
+ EXPECT_EQ(x, dragEvent->getX());
+ EXPECT_EQ(y, dragEvent->getY());
+
+ status = mConsumer->sendFinishedSignal(seq, true);
+ ASSERT_EQ(OK, status) << "consumer sendFinishedSignal should return OK";
+
+ uint32_t finishedSeq = 0;
+ bool handled = false;
+ nsecs_t consumeTime;
+ status = mPublisher->receiveFinishedSignal(
+ [&finishedSeq, &handled, &consumeTime](uint32_t inSeq, bool inHandled,
+ nsecs_t inConsumeTime) -> void {
+ finishedSeq = inSeq;
+ handled = inHandled;
+ consumeTime = inConsumeTime;
+ });
+ 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";
+ ASSERT_GE(consumeTime, publishTime)
+ << "finished signal's consume time should be greater than publish time";
+}
+
TEST_F(InputPublisherAndConsumerTest, PublishKeyEvent_EndToEnd) {
ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent());
}
@@ -403,6 +455,10 @@
ASSERT_NO_FATAL_FAILURE(PublishAndConsumeCaptureEvent());
}
+TEST_F(InputPublisherAndConsumerTest, PublishDragEvent_EndToEnd) {
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeDragEvent());
+}
+
TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenSequenceNumberIsZero_ReturnsError) {
status_t status;
const size_t pointerCount = 1;
@@ -468,6 +524,7 @@
ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent());
ASSERT_NO_FATAL_FAILURE(PublishAndConsumeCaptureEvent());
+ ASSERT_NO_FATAL_FAILURE(PublishAndConsumeDragEvent());
ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent());
}
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 8f43608..3d80b38 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -87,6 +87,12 @@
CHECK_OFFSET(InputMessage::Body::Capture, pointerCaptureEnabled, 4);
CHECK_OFFSET(InputMessage::Body::Capture, empty, 5);
+ CHECK_OFFSET(InputMessage::Body::Drag, eventId, 0);
+ CHECK_OFFSET(InputMessage::Body::Drag, x, 4);
+ CHECK_OFFSET(InputMessage::Body::Drag, y, 8);
+ CHECK_OFFSET(InputMessage::Body::Drag, isExiting, 12);
+ CHECK_OFFSET(InputMessage::Body::Drag, empty, 13);
+
CHECK_OFFSET(InputMessage::Body::Finished, handled, 0);
CHECK_OFFSET(InputMessage::Body::Finished, empty, 1);
CHECK_OFFSET(InputMessage::Body::Finished, consumeTime, 8);
@@ -110,6 +116,7 @@
static_assert(sizeof(InputMessage::Body::Finished) == 16);
static_assert(sizeof(InputMessage::Body::Focus) == 8);
static_assert(sizeof(InputMessage::Body::Capture) == 8);
+ static_assert(sizeof(InputMessage::Body::Drag) == 16);
}
// --- VerifiedInputEvent ---