Loading include/input/InputConsumerNoResampling.h +8 −7 Original line number Diff line number Diff line Loading @@ -211,16 +211,17 @@ private: * `consumeBatchedInputEvents`. */ std::map<DeviceId, std::queue<InputMessage>> mBatches; /** * Creates a MotionEvent by consuming samples from the provided queue. If one message has * eventTime > adjustedFrameTime, all subsequent messages in the queue will be skipped. It is * assumed that messages are queued in chronological order. In other words, only events that * occurred prior to the adjustedFrameTime will be consumed. * @param requestedFrameTime the time up to which to consume events. * @param messages the queue of messages to consume from * Creates a MotionEvent by consuming samples from the provided queue. Consumes all messages * with eventTime <= requestedFrameTime - resampleLatency, where `resampleLatency` is latency * introduced by the resampler. Assumes that messages are queued in chronological order. * @param requestedFrameTime The time up to which consume messages, as given by the inequality * above. If std::nullopt, everything in messages will be consumed. * @param messages the queue of messages to consume from. */ std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>> createBatchedMotionEvent( const nsecs_t requestedFrameTime, std::queue<InputMessage>& messages); const std::optional<nsecs_t> requestedFrameTime, std::queue<InputMessage>& messages); /** * Consumes the batched input events, optionally allowing the caller to specify a device id Loading libs/input/InputConsumerNoResampling.cpp +12 −9 Original line number Diff line number Diff line Loading @@ -357,7 +357,8 @@ void InputConsumerNoResampling::handleMessages(std::vector<InputMessage>&& messa mBatches[deviceId].emplace(msg); } else { // consume all pending batches for this device immediately consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/std::nullopt); consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/ std::numeric_limits<nsecs_t>::max()); if (canResample && (action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL)) { LOG_IF(INFO, mResamplers.erase(deviceId) == 0) Loading Loading @@ -480,7 +481,7 @@ void InputConsumerNoResampling::handleMessage(const InputMessage& msg) const { } std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>> InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrameTime, InputConsumerNoResampling::createBatchedMotionEvent(const std::optional<nsecs_t> requestedFrameTime, std::queue<InputMessage>& messages) { std::unique_ptr<MotionEvent> motionEvent; std::optional<uint32_t> firstSeqForBatch; Loading @@ -491,7 +492,11 @@ InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrame const nanoseconds resampleLatency = (resampler != mResamplers.cend()) ? resampler->second->getResampleLatency() : nanoseconds{0}; const nanoseconds adjustedFrameTime = nanoseconds{requestedFrameTime} - resampleLatency; // When batching is not enabled, we want to consume all events. That's equivalent to having an // infinite requestedFrameTime. const nanoseconds adjustedFrameTime = (requestedFrameTime.has_value()) ? (nanoseconds{*requestedFrameTime} - resampleLatency) : nanoseconds{std::numeric_limits<nsecs_t>::max()}; while (!messages.empty() && (messages.front().body.motion.eventTime <= adjustedFrameTime.count())) { Loading @@ -513,8 +518,9 @@ InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrame if (!messages.empty()) { futureSample = &messages.front(); } if ((motionEvent != nullptr) && (resampler != mResamplers.cend())) { resampler->second->resampleMotionEvent(nanoseconds{requestedFrameTime}, *motionEvent, if ((motionEvent != nullptr) && (resampler != mResamplers.cend()) && (requestedFrameTime.has_value())) { resampler->second->resampleMotionEvent(nanoseconds{*requestedFrameTime}, *motionEvent, futureSample); } Loading @@ -524,16 +530,13 @@ InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrame bool InputConsumerNoResampling::consumeBatchedInputEvents( std::optional<DeviceId> deviceId, std::optional<nsecs_t> requestedFrameTime) { ensureCalledOnLooperThread(__func__); // When batching is not enabled, we want to consume all events. That's equivalent to having an // infinite requestedFrameTime. requestedFrameTime = requestedFrameTime.value_or(std::numeric_limits<nsecs_t>::max()); bool producedEvents = false; for (auto deviceIdIter = (deviceId.has_value()) ? (mBatches.find(*deviceId)) : (mBatches.begin()); deviceIdIter != mBatches.cend(); ++deviceIdIter) { std::queue<InputMessage>& messages = deviceIdIter->second; auto [motion, firstSeqForBatch] = createBatchedMotionEvent(*requestedFrameTime, messages); auto [motion, firstSeqForBatch] = createBatchedMotionEvent(requestedFrameTime, messages); if (motion != nullptr) { LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value()); mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch); Loading libs/input/tests/InputConsumerResampling_test.cpp +28 −0 Original line number Diff line number Diff line Loading @@ -566,4 +566,32 @@ TEST_F(InputConsumerResamplingTest, OldEventReceivedAfterResampleOccurs) { mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true); } TEST_F(InputConsumerResamplingTest, DoNotResampleWhenFrameTimeIsNotAvailable) { mClientTestChannel->enqueueMessage(nextPointerMessage( {0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN})); invokeLooperCallback(); assertReceivedMotionEvent({InputEventEntry{0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN}}); mClientTestChannel->enqueueMessage(nextPointerMessage( {10ms, {Pointer{.id = 0, .x = 20.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE})); mClientTestChannel->enqueueMessage(nextPointerMessage( {20ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(std::nullopt); assertReceivedMotionEvent({InputEventEntry{10ms, {Pointer{.id = 0, .x = 20.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{20ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}}); mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true); } } // namespace android libs/input/tests/InputConsumer_test.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -194,7 +194,7 @@ TEST_F(InputConsumerTest, MessageStreamBatchedInMotionEvent) { std::unique_ptr<MotionEvent> moveMotionEvent = assertReceivedMotionEvent(WithMotionAction(ACTION_MOVE)); ASSERT_NE(moveMotionEvent, nullptr); EXPECT_EQ(moveMotionEvent->getHistorySize() + 1, 3UL); EXPECT_EQ(moveMotionEvent->getHistorySize() + 1, 2UL); mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true); Loading Loading @@ -443,4 +443,5 @@ TEST_F(InputConsumerTest, MultiDeviceResampling) { mClientTestChannel->assertFinishMessage(/*seq=*/8, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/10, /*handled=*/true); } } // namespace android Loading
include/input/InputConsumerNoResampling.h +8 −7 Original line number Diff line number Diff line Loading @@ -211,16 +211,17 @@ private: * `consumeBatchedInputEvents`. */ std::map<DeviceId, std::queue<InputMessage>> mBatches; /** * Creates a MotionEvent by consuming samples from the provided queue. If one message has * eventTime > adjustedFrameTime, all subsequent messages in the queue will be skipped. It is * assumed that messages are queued in chronological order. In other words, only events that * occurred prior to the adjustedFrameTime will be consumed. * @param requestedFrameTime the time up to which to consume events. * @param messages the queue of messages to consume from * Creates a MotionEvent by consuming samples from the provided queue. Consumes all messages * with eventTime <= requestedFrameTime - resampleLatency, where `resampleLatency` is latency * introduced by the resampler. Assumes that messages are queued in chronological order. * @param requestedFrameTime The time up to which consume messages, as given by the inequality * above. If std::nullopt, everything in messages will be consumed. * @param messages the queue of messages to consume from. */ std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>> createBatchedMotionEvent( const nsecs_t requestedFrameTime, std::queue<InputMessage>& messages); const std::optional<nsecs_t> requestedFrameTime, std::queue<InputMessage>& messages); /** * Consumes the batched input events, optionally allowing the caller to specify a device id Loading
libs/input/InputConsumerNoResampling.cpp +12 −9 Original line number Diff line number Diff line Loading @@ -357,7 +357,8 @@ void InputConsumerNoResampling::handleMessages(std::vector<InputMessage>&& messa mBatches[deviceId].emplace(msg); } else { // consume all pending batches for this device immediately consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/std::nullopt); consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/ std::numeric_limits<nsecs_t>::max()); if (canResample && (action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL)) { LOG_IF(INFO, mResamplers.erase(deviceId) == 0) Loading Loading @@ -480,7 +481,7 @@ void InputConsumerNoResampling::handleMessage(const InputMessage& msg) const { } std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>> InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrameTime, InputConsumerNoResampling::createBatchedMotionEvent(const std::optional<nsecs_t> requestedFrameTime, std::queue<InputMessage>& messages) { std::unique_ptr<MotionEvent> motionEvent; std::optional<uint32_t> firstSeqForBatch; Loading @@ -491,7 +492,11 @@ InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrame const nanoseconds resampleLatency = (resampler != mResamplers.cend()) ? resampler->second->getResampleLatency() : nanoseconds{0}; const nanoseconds adjustedFrameTime = nanoseconds{requestedFrameTime} - resampleLatency; // When batching is not enabled, we want to consume all events. That's equivalent to having an // infinite requestedFrameTime. const nanoseconds adjustedFrameTime = (requestedFrameTime.has_value()) ? (nanoseconds{*requestedFrameTime} - resampleLatency) : nanoseconds{std::numeric_limits<nsecs_t>::max()}; while (!messages.empty() && (messages.front().body.motion.eventTime <= adjustedFrameTime.count())) { Loading @@ -513,8 +518,9 @@ InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrame if (!messages.empty()) { futureSample = &messages.front(); } if ((motionEvent != nullptr) && (resampler != mResamplers.cend())) { resampler->second->resampleMotionEvent(nanoseconds{requestedFrameTime}, *motionEvent, if ((motionEvent != nullptr) && (resampler != mResamplers.cend()) && (requestedFrameTime.has_value())) { resampler->second->resampleMotionEvent(nanoseconds{*requestedFrameTime}, *motionEvent, futureSample); } Loading @@ -524,16 +530,13 @@ InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrame bool InputConsumerNoResampling::consumeBatchedInputEvents( std::optional<DeviceId> deviceId, std::optional<nsecs_t> requestedFrameTime) { ensureCalledOnLooperThread(__func__); // When batching is not enabled, we want to consume all events. That's equivalent to having an // infinite requestedFrameTime. requestedFrameTime = requestedFrameTime.value_or(std::numeric_limits<nsecs_t>::max()); bool producedEvents = false; for (auto deviceIdIter = (deviceId.has_value()) ? (mBatches.find(*deviceId)) : (mBatches.begin()); deviceIdIter != mBatches.cend(); ++deviceIdIter) { std::queue<InputMessage>& messages = deviceIdIter->second; auto [motion, firstSeqForBatch] = createBatchedMotionEvent(*requestedFrameTime, messages); auto [motion, firstSeqForBatch] = createBatchedMotionEvent(requestedFrameTime, messages); if (motion != nullptr) { LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value()); mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch); Loading
libs/input/tests/InputConsumerResampling_test.cpp +28 −0 Original line number Diff line number Diff line Loading @@ -566,4 +566,32 @@ TEST_F(InputConsumerResamplingTest, OldEventReceivedAfterResampleOccurs) { mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true); } TEST_F(InputConsumerResamplingTest, DoNotResampleWhenFrameTimeIsNotAvailable) { mClientTestChannel->enqueueMessage(nextPointerMessage( {0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN})); invokeLooperCallback(); assertReceivedMotionEvent({InputEventEntry{0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN}}); mClientTestChannel->enqueueMessage(nextPointerMessage( {10ms, {Pointer{.id = 0, .x = 20.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE})); mClientTestChannel->enqueueMessage(nextPointerMessage( {20ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(std::nullopt); assertReceivedMotionEvent({InputEventEntry{10ms, {Pointer{.id = 0, .x = 20.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{20ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}}); mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true); } } // namespace android
libs/input/tests/InputConsumer_test.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -194,7 +194,7 @@ TEST_F(InputConsumerTest, MessageStreamBatchedInMotionEvent) { std::unique_ptr<MotionEvent> moveMotionEvent = assertReceivedMotionEvent(WithMotionAction(ACTION_MOVE)); ASSERT_NE(moveMotionEvent, nullptr); EXPECT_EQ(moveMotionEvent->getHistorySize() + 1, 3UL); EXPECT_EQ(moveMotionEvent->getHistorySize() + 1, 2UL); mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true); Loading Loading @@ -443,4 +443,5 @@ TEST_F(InputConsumerTest, MultiDeviceResampling) { mClientTestChannel->assertFinishMessage(/*seq=*/8, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/10, /*handled=*/true); } } // namespace android