diff options
author | 2024-09-29 23:55:23 +0000 | |
---|---|---|
committer | 2024-10-06 23:11:33 +0000 | |
commit | 7f1efed1f8fcae76c021bfcea244c4f92844a608 (patch) | |
tree | 25382ef1de8c8d21492436587d7c2567747a4411 | |
parent | 5d59a429f0b0954f8183d4931db8417e308efca8 (diff) |
Add check to not resample when resample time equals motion event time
Included SampleTimeEqualsEventTime from TouchResampling_test.cpp into
InputConsumerResampling_test.cpp, and added the missing logic in
LegacyResampler to pass the test.
Bug: 297226446
Flag: EXEMPT refactor
Test: TEST=libinput_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST --gtest_filter="InputConsumerResamplingTest*"
Change-Id: I8ff9a263ea79eed1b814d2b1ce0b7efb5ade584e
-rw-r--r-- | include/input/Resampler.h | 3 | ||||
-rw-r--r-- | libs/input/Resampler.cpp | 5 | ||||
-rw-r--r-- | libs/input/tests/InputConsumerResampling_test.cpp | 51 |
3 files changed, 51 insertions, 8 deletions
diff --git a/include/input/Resampler.h b/include/input/Resampler.h index 4aaeddd159..da0c5b2150 100644 --- a/include/input/Resampler.h +++ b/include/input/Resampler.h @@ -65,7 +65,8 @@ public: * extrapolation takes place and `resampleTime` is too far in the future. If `futureSample` is * not null, interpolation will occur. If `futureSample` is null and there is enough historical * data, LegacyResampler will extrapolate. Otherwise, no resampling takes place and - * `motionEvent` is unmodified. + * `motionEvent` is unmodified. Furthermore, motionEvent is not resampled if resampleTime equals + * the last sample eventTime of motionEvent. */ void resampleMotionEvent(std::chrono::nanoseconds frameTime, MotionEvent& motionEvent, const InputMessage* futureSample) override; diff --git a/libs/input/Resampler.cpp b/libs/input/Resampler.cpp index 328fa684f6..1adff7ba36 100644 --- a/libs/input/Resampler.cpp +++ b/libs/input/Resampler.cpp @@ -249,6 +249,11 @@ void LegacyResampler::resampleMotionEvent(nanoseconds frameTime, MotionEvent& mo const InputMessage* futureSample) { const nanoseconds resampleTime = frameTime - RESAMPLE_LATENCY; + if (resampleTime.count() == motionEvent.getEventTime()) { + LOG_IF(INFO, debugResampling()) << "Not resampled. Resample time equals motion event time."; + return; + } + updateLatestSamples(motionEvent); const std::optional<Sample> sample = (futureSample != nullptr) diff --git a/libs/input/tests/InputConsumerResampling_test.cpp b/libs/input/tests/InputConsumerResampling_test.cpp index 61a0a98c9e..b139e8766f 100644 --- a/libs/input/tests/InputConsumerResampling_test.cpp +++ b/libs/input/tests/InputConsumerResampling_test.cpp @@ -1,4 +1,3 @@ - /* * Copyright (C) 2024 The Android Open Source Project * @@ -193,7 +192,7 @@ void InputConsumerResamplingTest::assertReceivedMotionEvent( * last two real events, which would put this time at: 20 ms + (20 ms - 10 ms) / 2 = 25 ms. */ TEST_F(InputConsumerResamplingTest, EventIsResampled) { - // Initial ACTION_DOWN should be separate, because the first consume event will only return + // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an // InputEvent with a single action. mClientTestChannel->enqueueMessage(nextPointerMessage( {0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN})); @@ -234,7 +233,7 @@ TEST_F(InputConsumerResamplingTest, EventIsResampled) { * have these hardcoded. */ TEST_F(InputConsumerResamplingTest, EventIsResampledWithDifferentId) { - // Initial ACTION_DOWN should be separate, because the first consume event will only return + // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an // InputEvent with a single action. mClientTestChannel->enqueueMessage(nextPointerMessage( {0ms, {Pointer{.id = 1, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN})); @@ -274,7 +273,7 @@ TEST_F(InputConsumerResamplingTest, EventIsResampledWithDifferentId) { * Stylus pointer coordinates are resampled. */ TEST_F(InputConsumerResamplingTest, StylusEventIsResampled) { - // Initial ACTION_DOWN should be separate, because the first consume event will only return + // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an // InputEvent with a single action. mClientTestChannel->enqueueMessage(nextPointerMessage( {0ms, @@ -332,9 +331,8 @@ TEST_F(InputConsumerResamplingTest, StylusEventIsResampled) { * Mouse pointer coordinates are resampled. */ TEST_F(InputConsumerResamplingTest, MouseEventIsResampled) { - // Initial ACTION_DOWN should be separate, because the first consume event will only return + // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an // InputEvent with a single action. - mClientTestChannel->enqueueMessage(nextPointerMessage( {0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f, .toolType = ToolType::MOUSE}}, @@ -391,7 +389,7 @@ TEST_F(InputConsumerResamplingTest, MouseEventIsResampled) { * Motion events with palm tool type are not resampled. */ TEST_F(InputConsumerResamplingTest, PalmEventIsNotResampled) { - // Initial ACTION_DOWN should be separate, because the first consume event will only return + // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an // InputEvent with a single action. mClientTestChannel->enqueueMessage(nextPointerMessage( {0ms, @@ -431,4 +429,43 @@ TEST_F(InputConsumerResamplingTest, PalmEventIsNotResampled) { mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true); } +/** + * Event should not be resampled when sample time is equal to event time. + */ +TEST_F(InputConsumerResamplingTest, SampleTimeEqualsEventTime) { + // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an + // InputEvent with a single action. + mClientTestChannel->enqueueMessage(nextPointerMessage( + {0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN})); + + mClientTestChannel->assertNoSentMessages(); + + invokeLooperCallback(); + assertReceivedMotionEvent({InputEventEntry{0ms, + {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, + AMOTION_EVENT_ACTION_DOWN}}); + + // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y + 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(nanoseconds{20ms + 5ms /*RESAMPLE_LATENCY*/}.count()); + + // MotionEvent should not resampled because the resample time falls exactly on the existing + // event time. + 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 |