diff options
author | 2021-07-20 23:53:10 +0000 | |
---|---|---|
committer | 2021-07-20 23:53:10 +0000 | |
commit | 2ab7a803bb4e934cbf8d08384fcaf5028cfed59e (patch) | |
tree | d29d6c7e2f3908a157b61d514b886cf739705802 | |
parent | 57ca2a902aa9714c59ebd822f78fea9ca66d9f46 (diff) | |
parent | 7cdf8ef17636cdc5cc5fe41578951b4b1f23865c (diff) |
Merge "TouchEvent (1/n): Adding TouchModeEvent to InputChannel"
-rw-r--r-- | include/android/input.h | 3 | ||||
-rw-r--r-- | include/input/Input.h | 24 | ||||
-rw-r--r-- | include/input/InputTransport.h | 20 | ||||
-rw-r--r-- | libs/input/Input.cpp | 25 | ||||
-rw-r--r-- | libs/input/InputTransport.cpp | 42 | ||||
-rw-r--r-- | libs/input/tests/InputPublisherAndConsumer_test.cpp | 46 | ||||
-rw-r--r-- | libs/input/tests/StructLayout_test.cpp | 5 |
7 files changed, 165 insertions, 0 deletions
diff --git a/include/android/input.h b/include/android/input.h index bb98beb41a..f03facb929 100644 --- a/include/android/input.h +++ b/include/android/input.h @@ -169,6 +169,9 @@ enum { /** Drag event */ AINPUT_EVENT_TYPE_DRAG = 5, + + /** TouchMode event */ + AINPUT_EVENT_TYPE_TOUCH_MODE = 6, }; /** diff --git a/include/input/Input.h b/include/input/Input.h index cd9b486b9c..2e424097e1 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -886,6 +886,25 @@ protected: float mX, mY; }; +/* + * Touch mode events. + */ +class TouchModeEvent : public InputEvent { +public: + virtual ~TouchModeEvent() {} + + virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_TOUCH_MODE; } + + inline bool isInTouchMode() const { return mIsInTouchMode; } + + void initialize(int32_t id, bool isInTouchMode); + + void initialize(const TouchModeEvent& from); + +protected: + bool mIsInTouchMode; +}; + /** * Base class for verified events. * Do not create a VerifiedInputEvent explicitly. @@ -950,6 +969,7 @@ public: virtual FocusEvent* createFocusEvent() = 0; virtual CaptureEvent* createCaptureEvent() = 0; virtual DragEvent* createDragEvent() = 0; + virtual TouchModeEvent* createTouchModeEvent() = 0; }; /* @@ -966,6 +986,7 @@ public: virtual FocusEvent* createFocusEvent() override { return &mFocusEvent; } virtual CaptureEvent* createCaptureEvent() override { return &mCaptureEvent; } virtual DragEvent* createDragEvent() override { return &mDragEvent; } + virtual TouchModeEvent* createTouchModeEvent() override { return &mTouchModeEvent; } private: KeyEvent mKeyEvent; @@ -973,6 +994,7 @@ private: FocusEvent mFocusEvent; CaptureEvent mCaptureEvent; DragEvent mDragEvent; + TouchModeEvent mTouchModeEvent; }; /* @@ -988,6 +1010,7 @@ public: virtual FocusEvent* createFocusEvent() override; virtual CaptureEvent* createCaptureEvent() override; virtual DragEvent* createDragEvent() override; + virtual TouchModeEvent* createTouchModeEvent() override; void recycle(InputEvent* event); @@ -999,6 +1022,7 @@ private: std::queue<std::unique_ptr<FocusEvent>> mFocusEventPool; std::queue<std::unique_ptr<CaptureEvent>> mCaptureEventPool; std::queue<std::unique_ptr<DragEvent>> mDragEventPool; + std::queue<std::unique_ptr<TouchModeEvent>> mTouchModeEventPool; }; } // namespace android diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index a790b5637f..9a150eb0e2 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -72,6 +72,7 @@ struct InputMessage { CAPTURE, DRAG, TIMELINE, + TOUCH_MODE, }; struct Header { @@ -206,6 +207,15 @@ struct InputMessage { inline size_t size() const { return sizeof(Timeline); } } timeline; + + struct TouchMode { + int32_t eventId; + // The following 2 fields take up 4 bytes total + bool isInTouchMode; + uint8_t empty[3]; + + inline size_t size() const { return sizeof(TouchMode); } + } touchMode; } __attribute__((aligned(8))) body; bool isValid(size_t actualSize) const; @@ -388,6 +398,15 @@ public: */ status_t publishDragEvent(uint32_t seq, int32_t eventId, float x, float y, bool isExiting); + /* Publishes a touch mode 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 publishTouchModeEvent(uint32_t seq, int32_t eventId, bool isInTouchMode); + struct Finished { uint32_t seq; bool handled; @@ -658,6 +677,7 @@ private: 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 initializeTouchModeEvent(TouchModeEvent* 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 82a814f293..53a8c4f16f 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -160,6 +160,9 @@ const char* inputEventTypeToString(int32_t type) { case AINPUT_EVENT_TYPE_DRAG: { return "DRAG"; } + case AINPUT_EVENT_TYPE_TOUCH_MODE: { + return "TOUCH_MODE"; + } } return "UNKNOWN"; } @@ -883,6 +886,19 @@ void DragEvent::initialize(const DragEvent& from) { mY = from.mY; } +// --- TouchModeEvent --- + +void TouchModeEvent::initialize(int32_t id, bool isInTouchMode) { + InputEvent::initialize(id, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN, + ADISPLAY_ID_NONE, INVALID_HMAC); + mIsInTouchMode = isInTouchMode; +} + +void TouchModeEvent::initialize(const TouchModeEvent& from) { + InputEvent::initialize(from); + mIsInTouchMode = from.mIsInTouchMode; +} + // --- PooledInputEventFactory --- PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) : @@ -937,6 +953,15 @@ DragEvent* PooledInputEventFactory::createDragEvent() { return event; } +TouchModeEvent* PooledInputEventFactory::createTouchModeEvent() { + if (mTouchModeEventPool.empty()) { + return new TouchModeEvent(); + } + TouchModeEvent* event = mTouchModeEventPool.front().release(); + mTouchModeEventPool.pop(); + return event; +} + void PooledInputEventFactory::recycle(InputEvent* event) { switch (event->getType()) { case AINPUT_EVENT_TYPE_KEY: diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index ea8b9a7ec8..1e93dfb488 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -116,6 +116,7 @@ bool InputMessage::isValid(size_t actualSize) const { case Type::FOCUS: case Type::CAPTURE: case Type::DRAG: + case Type::TOUCH_MODE: return true; case Type::TIMELINE: { const nsecs_t gpuCompletedTime = @@ -151,6 +152,8 @@ size_t InputMessage::size() const { return sizeof(Header) + body.drag.size(); case Type::TIMELINE: return sizeof(Header) + body.timeline.size(); + case Type::TOUCH_MODE: + return sizeof(Header) + body.touchMode.size(); } return sizeof(Header); } @@ -293,6 +296,10 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { msg->body.timeline.graphicsTimeline = body.timeline.graphicsTimeline; break; } + case InputMessage::Type::TOUCH_MODE: { + msg->body.touchMode.eventId = body.touchMode.eventId; + msg->body.touchMode.isInTouchMode = body.touchMode.isInTouchMode; + } } } @@ -665,6 +672,22 @@ status_t InputPublisher::publishDragEvent(uint32_t seq, int32_t eventId, float x return mChannel->sendMessage(&msg); } +status_t InputPublisher::publishTouchModeEvent(uint32_t seq, int32_t eventId, bool isInTouchMode) { + if (ATRACE_ENABLED()) { + std::string message = + StringPrintf("publishTouchModeEvent(inputChannel=%s, isInTouchMode=%s)", + mChannel->getName().c_str(), toString(isInTouchMode)); + ATRACE_NAME(message.c_str()); + } + + InputMessage msg; + msg.header.type = InputMessage::Type::TOUCH_MODE; + msg.header.seq = seq; + msg.body.touchMode.eventId = eventId; + msg.body.touchMode.isInTouchMode = isInTouchMode; + return mChannel->sendMessage(&msg); +} + android::base::Result<InputPublisher::ConsumerResponse> InputPublisher::receiveConsumerResponse() { if (DEBUG_TRANSPORT_ACTIONS) { ALOGD("channel '%s' publisher ~ %s", mChannel->getName().c_str(), __func__); @@ -866,6 +889,16 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consum *outEvent = dragEvent; break; } + + case InputMessage::Type::TOUCH_MODE: { + TouchModeEvent* touchModeEvent = factory->createTouchModeEvent(); + if (!touchModeEvent) return NO_MEMORY; + + initializeTouchModeEvent(touchModeEvent, &mMsg); + *outSeq = mMsg.header.seq; + *outEvent = touchModeEvent; + break; + } } } return OK; @@ -1370,6 +1403,10 @@ void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage msg->body.motion.eventTime, pointerCount, pointerProperties, pointerCoords); } +void InputConsumer::initializeTouchModeEvent(TouchModeEvent* event, const InputMessage* msg) { + event->initialize(msg->body.touchMode.eventId, msg->body.touchMode.isInTouchMode); +} + void InputConsumer::addSample(MotionEvent* event, const InputMessage* msg) { uint32_t pointerCount = msg->body.motion.pointerCount; PointerCoords pointerCoords[pointerCount]; @@ -1476,6 +1513,11 @@ std::string InputConsumer::dump() const { presentTime); break; } + case InputMessage::Type::TOUCH_MODE: { + out += android::base::StringPrintf("isInTouchMode=%s", + toString(msg.body.touchMode.isInTouchMode)); + break; + } } out += "\n"; } diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index 5d1f2c3bfc..8db5bf1289 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -56,6 +56,7 @@ protected: void PublishAndConsumeFocusEvent(); void PublishAndConsumeCaptureEvent(); void PublishAndConsumeDragEvent(); + void PublishAndConsumeTouchModeEvent(); }; TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) { @@ -413,6 +414,46 @@ void InputPublisherAndConsumerTest::PublishAndConsumeDragEvent() { << "finished signal's consume time should be greater than publish time"; } +void InputPublisherAndConsumerTest::PublishAndConsumeTouchModeEvent() { + status_t status; + + constexpr uint32_t seq = 15; + int32_t eventId = InputEvent::nextId(); + constexpr bool touchModeEnabled = true; + const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC); + + status = mPublisher->publishTouchModeEvent(seq, eventId, touchModeEnabled); + ASSERT_EQ(OK, status) << "publisher publishTouchModeEvent 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_TOUCH_MODE, event->getType()) + << "consumer should have returned a touch mode event"; + + const TouchModeEvent& touchModeEvent = static_cast<const TouchModeEvent&>(*event); + EXPECT_EQ(seq, consumeSeq); + EXPECT_EQ(eventId, touchModeEvent.getId()); + EXPECT_EQ(touchModeEnabled, touchModeEvent.isInTouchMode()); + + status = mConsumer->sendFinishedSignal(seq, true); + ASSERT_EQ(OK, status) << "consumer sendFinishedSignal should return OK"; + + Result<InputPublisher::ConsumerResponse> result = mPublisher->receiveConsumerResponse(); + ASSERT_TRUE(result.ok()) << "receiveConsumerResponse should return OK"; + ASSERT_TRUE(std::holds_alternative<InputPublisher::Finished>(*result)); + const InputPublisher::Finished& finish = std::get<InputPublisher::Finished>(*result); + ASSERT_EQ(seq, finish.seq) + << "receiveConsumerResponse should have returned the original sequence number"; + ASSERT_TRUE(finish.handled) + << "receiveConsumerResponse should have set handled to consumer's reply"; + ASSERT_GE(finish.consumeTime, publishTime) + << "finished signal's consume time should be greater than publish time"; +} + TEST_F(InputPublisherAndConsumerTest, SendTimeline) { const int32_t inputEventId = 20; std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline; @@ -449,6 +490,10 @@ TEST_F(InputPublisherAndConsumerTest, PublishDragEvent_EndToEnd) { ASSERT_NO_FATAL_FAILURE(PublishAndConsumeDragEvent()); } +TEST_F(InputPublisherAndConsumerTest, PublishTouchModeEvent_EndToEnd) { + ASSERT_NO_FATAL_FAILURE(PublishAndConsumeTouchModeEvent()); +} + TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenSequenceNumberIsZero_ReturnsError) { status_t status; const size_t pointerCount = 1; @@ -520,6 +565,7 @@ TEST_F(InputPublisherAndConsumerTest, PublishMultipleEvents_EndToEnd) { ASSERT_NO_FATAL_FAILURE(PublishAndConsumeDragEvent()); ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent()); + ASSERT_NO_FATAL_FAILURE(PublishAndConsumeTouchModeEvent()); } } // namespace android diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp index 59fed1fb41..18289a5f11 100644 --- a/libs/input/tests/StructLayout_test.cpp +++ b/libs/input/tests/StructLayout_test.cpp @@ -102,6 +102,10 @@ void TestInputMessageAlignment() { CHECK_OFFSET(InputMessage::Body::Timeline, eventId, 0); CHECK_OFFSET(InputMessage::Body::Timeline, empty, 4); CHECK_OFFSET(InputMessage::Body::Timeline, graphicsTimeline, 8); + + CHECK_OFFSET(InputMessage::Body::TouchMode, eventId, 0); + CHECK_OFFSET(InputMessage::Body::TouchMode, isInTouchMode, 4); + CHECK_OFFSET(InputMessage::Body::TouchMode, empty, 5); } void TestHeaderSize() { @@ -123,6 +127,7 @@ void TestBodySize() { static_assert(sizeof(InputMessage::Body::Focus) == 8); static_assert(sizeof(InputMessage::Body::Capture) == 8); static_assert(sizeof(InputMessage::Body::Drag) == 16); + static_assert(sizeof(InputMessage::Body::TouchMode) == 8); // Timeline static_assert(GraphicsTimeline::SIZE == 2); static_assert(sizeof(InputMessage::Body::Timeline) == 24); |