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