diff options
author | 2020-12-30 16:58:01 +0800 | |
---|---|---|
committer | 2021-03-08 21:40:13 +0800 | |
commit | 7632c3391394a47cface411997ce03d126d1e4da (patch) | |
tree | f4c4ab55383c089cb766c95442dfd958a5c78fb3 | |
parent | 335c73a433ab3e7e158204d09a6f1f5f6a2ff1dc (diff) |
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
-rw-r--r-- | include/android/input.h | 3 | ||||
-rw-r--r-- | include/input/Input.h | 29 | ||||
-rw-r--r-- | include/input/InputTransport.h | 21 | ||||
-rw-r--r-- | libs/input/Input.cpp | 35 | ||||
-rw-r--r-- | libs/input/InputTransport.cpp | 51 | ||||
-rw-r--r-- | libs/input/tests/InputPublisherAndConsumer_test.cpp | 61 | ||||
-rw-r--r-- | libs/input/tests/StructLayout_test.cpp | 7 |
7 files changed, 205 insertions, 2 deletions
diff --git a/include/android/input.h b/include/android/input.h index 797348742d..6fe95c0fc3 100644 --- a/include/android/input.h +++ b/include/android/input.h @@ -166,6 +166,9 @@ enum { /** Capture event */ AINPUT_EVENT_TYPE_CAPTURE = 4, + + /** Drag event */ + AINPUT_EVENT_TYPE_DRAG = 5, }; /** diff --git a/include/input/Input.h b/include/input/Input.h index aa42db8ea8..f9fe6b9597 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -792,6 +792,30 @@ protected: bool mPointerCaptureEnabled; }; +/* + * Drag events. + */ +class DragEvent : public InputEvent { +public: + virtual ~DragEvent() {} + + virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_DRAG; } + + inline bool isExiting() const { return mIsExiting; } + + inline float getX() const { return mX; } + + inline float getY() const { return mY; } + + void initialize(int32_t id, float x, float y, bool isExiting); + + void initialize(const DragEvent& from); + +protected: + bool mIsExiting; + float mX, mY; +}; + /** * Base class for verified events. * Do not create a VerifiedInputEvent explicitly. @@ -855,6 +879,7 @@ public: virtual MotionEvent* createMotionEvent() = 0; virtual FocusEvent* createFocusEvent() = 0; virtual CaptureEvent* createCaptureEvent() = 0; + virtual DragEvent* createDragEvent() = 0; }; /* @@ -870,12 +895,14 @@ public: virtual MotionEvent* createMotionEvent() override { return &mMotionEvent; } virtual FocusEvent* createFocusEvent() override { return &mFocusEvent; } virtual CaptureEvent* createCaptureEvent() override { return &mCaptureEvent; } + virtual DragEvent* createDragEvent() override { return &mDragEvent; } private: KeyEvent mKeyEvent; MotionEvent mMotionEvent; FocusEvent mFocusEvent; CaptureEvent mCaptureEvent; + DragEvent mDragEvent; }; /* @@ -890,6 +917,7 @@ public: virtual MotionEvent* createMotionEvent() override; virtual FocusEvent* createFocusEvent() override; virtual CaptureEvent* createCaptureEvent() override; + virtual DragEvent* createDragEvent() override; void recycle(InputEvent* event); @@ -900,6 +928,7 @@ private: std::queue<std::unique_ptr<MotionEvent>> mMotionEventPool; std::queue<std::unique_ptr<FocusEvent>> mFocusEventPool; std::queue<std::unique_ptr<CaptureEvent>> mCaptureEventPool; + std::queue<std::unique_ptr<DragEvent>> mDragEventPool; }; } // namespace android diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index ba9ae204eb..f1b22587ce 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -69,6 +69,7 @@ struct InputMessage { FINISHED, FOCUS, CAPTURE, + DRAG, }; struct Header { @@ -183,6 +184,16 @@ struct InputMessage { inline size_t size() const { return sizeof(Capture); } } capture; + + struct Drag { + int32_t eventId; + float x; + float y; + bool isExiting; + uint8_t empty[3]; + + inline size_t size() const { return sizeof(Drag); } + } drag; } __attribute__((aligned(8))) body; bool isValid(size_t actualSize) const; @@ -354,6 +365,15 @@ public: */ status_t publishCaptureEvent(uint32_t seq, int32_t eventId, bool pointerCaptureEnabled); + /* Publishes a drag event to the input channel. + * + * Returns OK on success. + * Returns WOULD_BLOCK if the channel is full. + * Returns DEAD_OBJECT if the channel's peer has been closed. + * Other errors probably indicate that the channel is broken. + */ + status_t publishDragEvent(uint32_t seq, int32_t eventId, float x, float y, bool isExiting); + /* Receives the finished signal from the consumer in reply to the original dispatch signal. * If a signal was received, returns the message sequence number, * whether the consumer handled the message, and the time the event was first read by the @@ -601,6 +621,7 @@ private: static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg); static void initializeFocusEvent(FocusEvent* event, const InputMessage* msg); static void initializeCaptureEvent(CaptureEvent* event, const InputMessage* msg); + static void initializeDragEvent(DragEvent* event, const InputMessage* msg); static void addSample(MotionEvent* event, const InputMessage* msg); static bool canAddSample(const Batch& batch, const InputMessage* msg); static ssize_t findSampleNoLaterThan(const Batch& batch, nsecs_t time); diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index 0a00d68556..5600eb3f5e 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -92,6 +92,9 @@ const char* inputEventTypeToString(int32_t type) { case AINPUT_EVENT_TYPE_CAPTURE: { return "CAPTURE"; } + case AINPUT_EVENT_TYPE_DRAG: { + return "DRAG"; + } } return "UNKNOWN"; } @@ -770,6 +773,23 @@ void CaptureEvent::initialize(const CaptureEvent& from) { 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 @@ CaptureEvent* PooledInputEventFactory::createCaptureEvent() { 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 @@ void PooledInputEventFactory::recycle(InputEvent* event) { 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 ee2daec5fc..6ef01737f9 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -108,6 +108,8 @@ bool InputMessage::isValid(size_t actualSize) const { return true; case Type::CAPTURE: return true; + case Type::DRAG: + return true; } } return false; @@ -125,6 +127,8 @@ size_t InputMessage::size() const { 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 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { 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 @@ status_t InputPublisher::publishCaptureEvent(uint32_t seq, int32_t eventId, 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 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consum *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 @@ void InputConsumer::initializeCaptureEvent(CaptureEvent* event, const InputMessa 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 @@ std::string InputConsumer::dump() const { .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 e7e566dde6..b5ed8d7ba7 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -52,6 +52,7 @@ protected: void PublishAndConsumeMotionEvent(); void PublishAndConsumeFocusEvent(); void PublishAndConsumeCaptureEvent(); + void PublishAndConsumeDragEvent(); }; TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) { @@ -301,7 +302,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeFocusEvent() { 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 @@ void InputPublisherAndConsumerTest::PublishAndConsumeCaptureEvent() { 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 @@ void InputPublisherAndConsumerTest::PublishAndConsumeCaptureEvent() { << "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 @@ TEST_F(InputPublisherAndConsumerTest, PublishCaptureEvent_EndToEnd) { 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 @@ TEST_F(InputPublisherAndConsumerTest, PublishMultipleEvents_EndToEnd) { 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 8f436085f7..3d80b38636 100644 --- a/libs/input/tests/StructLayout_test.cpp +++ b/libs/input/tests/StructLayout_test.cpp @@ -87,6 +87,12 @@ void TestInputMessageAlignment() { 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 @@ void TestBodySize() { 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 --- |