diff options
author | 2024-09-11 22:20:26 +0000 | |
---|---|---|
committer | 2024-09-17 23:47:44 +0000 | |
commit | 6affbdb94fb86697e92503770ac0dcaea2a16dc0 (patch) | |
tree | 178f0f5cdade64128b2770b4b1874d2515831361 | |
parent | e2bb18735b214e773c0039581a1fa1771f442c71 (diff) |
Update Resampler_test.cpp to consider RESAMPLE_LATENCY
Updated Resampler_test.cpp to consider RESAMPLE_LATENCY because the
parameter was unused in Resampler.cpp
Bug: 297226446
Flag: EXEMPT refactor
Test: TEST=libinput_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST --gtest_filter="ResamplerTest*"
Change-Id: I965264e88bede4be74025f61bcd4ef8d235dc4c8
-rw-r--r-- | include/input/Resampler.h | 11 | ||||
-rw-r--r-- | libs/input/Resampler.cpp | 4 | ||||
-rw-r--r-- | libs/input/tests/Resampler_test.cpp | 115 |
3 files changed, 75 insertions, 55 deletions
diff --git a/include/input/Resampler.h b/include/input/Resampler.h index 2892137ae7..67d92bd3ad 100644 --- a/include/input/Resampler.h +++ b/include/input/Resampler.h @@ -35,9 +35,9 @@ struct Resampler { virtual ~Resampler() = default; /** - * Tries to resample motionEvent at resampleTime. The provided resampleTime must be greater than + * Tries to resample motionEvent at frameTime. The provided frameTime must be greater than * the latest sample time of motionEvent. It is not guaranteed that resampling occurs at - * resampleTime. Interpolation may occur is futureSample is available. Otherwise, motionEvent + * frameTime. Interpolation may occur is futureSample is available. Otherwise, motionEvent * may be resampled by another method, or not resampled at all. Furthermore, it is the * implementer's responsibility to guarantee the following: * - If resampling occurs, a single additional sample should be added to motionEvent. That is, @@ -45,15 +45,14 @@ struct Resampler { * samples by the end of the resampling. No other field of motionEvent should be modified. * - If resampling does not occur, then motionEvent must not be modified in any way. */ - virtual void resampleMotionEvent(std::chrono::nanoseconds resampleTime, - MotionEvent& motionEvent, + virtual void resampleMotionEvent(std::chrono::nanoseconds frameTime, MotionEvent& motionEvent, const InputMessage* futureSample) = 0; }; class LegacyResampler final : public Resampler { public: /** - * Tries to resample `motionEvent` at `resampleTime` by adding a resampled sample at the end of + * Tries to resample `motionEvent` at `frameTime` by adding a resampled sample at the end of * `motionEvent` with eventTime equal to `resampleTime` and pointer coordinates determined by * linear interpolation or linear extrapolation. An earlier `resampleTime` will be used if * extrapolation takes place and `resampleTime` is too far in the future. If `futureSample` is @@ -61,7 +60,7 @@ public: * data, LegacyResampler will extrapolate. Otherwise, no resampling takes place and * `motionEvent` is unmodified. */ - void resampleMotionEvent(std::chrono::nanoseconds resampleTime, MotionEvent& motionEvent, + void resampleMotionEvent(std::chrono::nanoseconds frameTime, MotionEvent& motionEvent, const InputMessage* futureSample) override; private: diff --git a/libs/input/Resampler.cpp b/libs/input/Resampler.cpp index c663649091..b535ff42c4 100644 --- a/libs/input/Resampler.cpp +++ b/libs/input/Resampler.cpp @@ -241,13 +241,15 @@ inline void LegacyResampler::addSampleToMotionEvent(const Sample& sample, motionEvent.getId()); } -void LegacyResampler::resampleMotionEvent(nanoseconds resampleTime, MotionEvent& motionEvent, +void LegacyResampler::resampleMotionEvent(nanoseconds frameTime, MotionEvent& motionEvent, const InputMessage* futureSample) { if (mPreviousDeviceId && *mPreviousDeviceId != motionEvent.getDeviceId()) { mLatestSamples.clear(); } mPreviousDeviceId = motionEvent.getDeviceId(); + const nanoseconds resampleTime = frameTime - RESAMPLE_LATENCY; + updateLatestSamples(motionEvent); const std::optional<Sample> sample = (futureSample != nullptr) diff --git a/libs/input/tests/Resampler_test.cpp b/libs/input/tests/Resampler_test.cpp index 7ae9a28664..26dee393c1 100644 --- a/libs/input/tests/Resampler_test.cpp +++ b/libs/input/tests/Resampler_test.cpp @@ -120,6 +120,47 @@ InputStream::operator MotionEvent() const { } // namespace +/** + * The testing setup assumes an input rate of 200 Hz and a display rate of 60 Hz. This implies that + * input events are received every 5 milliseconds, while the display consumes batched events every + * ~16 milliseconds. The resampler's RESAMPLE_LATENCY constant determines the resample time, which + * is calculated as frameTime - RESAMPLE_LATENCY. resampleTime specifies the time used for + * resampling. For example, if the desired frame time consumption is ~16 milliseconds, the resample + * time would be ~11 milliseconds. Consequenly, the last added sample to the motion event has an + * event time of ~11 milliseconds. Note that there are specific scenarios where resampleMotionEvent + * is not called with a multiple of ~16 milliseconds. These cases are primarily for data addition + * or to test other functionalities of the resampler. + * + * Coordinates are calculated using linear interpolation (lerp) based on the last two available + * samples. Linear interpolation is defined as (a + alpha*(b - a)). Let t_b and t_a be the + * timestamps of samples a and b, respectively. The interpolation factor alpha is calculated as + * (resampleTime - t_a) / (t_b - t_a). The value of alpha determines whether the resampled + * coordinates are interpolated or extrapolated. If alpha falls within the semi-closed interval [0, + * 1), the coordinates are interpolated. If alpha is greater than or equal to 1, the coordinates are + * extrapolated. + * + * The timeline below depics an interpolation scenario + * -----------------------------------|---------|---------|---------|---------- + * 10ms 11ms 15ms 16ms + * MOVE | MOVE | + * resampleTime frameTime + * Based on the timeline alpha is (11 - 10)/(15 - 10) = 1/5. Thus, coordinates are interpolated. + * + * The following timeline portrays an extrapolation scenario + * -------------------------|---------|---------|-------------------|---------- + * 5ms 10ms 11ms 16ms + * MOVE MOVE | | + * resampleTime frameTime + * Likewise, alpha = (11 - 5)/(10 - 5) = 6/5. Hence, coordinates are extrapolated. + * + * If a motion event was resampled, the tests will check that the following conditions are satisfied + * to guarantee resampling correctness: + * - The motion event metadata must not change. + * - The number of samples in the motion event must only increment by 1. + * - The resampled values must be at the end of motion event coordinates. + * - The rasamples values must be near the hand calculations. + * - The resampled time must be the most recent one in motion event. + */ class ResamplerTest : public testing::Test { protected: ResamplerTest() : mResampler(std::make_unique<LegacyResampler>()) {} @@ -225,7 +266,7 @@ TEST_F(ResamplerTest, NonResampledAxesArePreserved) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample); + mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample); EXPECT_EQ(motionEvent.getTouchMajor(0), TOUCH_MAJOR_VALUE); @@ -243,7 +284,7 @@ TEST_F(ResamplerTest, SinglePointerNotEnoughDataToResample) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr); + mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr); assertMotionEventIsNotResampled(originalMotionEvent, motionEvent); } @@ -270,23 +311,6 @@ TEST_F(ResamplerTest, SinglePointerDifferentDeviceIdBetweenMotionEvents) { assertMotionEventIsNotResampled(originalMotionEvent, motionFromSecondDevice); } -// Increments of 16 ms for display refresh rate -// Increments of 6 ms for input frequency -// Resampling latency is known to be 5 ms -// Therefore, first resampling time will be 11 ms - -/** - * Timeline - * ----+----------------------+---------+---------+---------+---------- - * 0ms 10ms 11ms 15ms 16ms - * DOWN MOVE | MSG | - * resample frame - * Resampling occurs at 11ms. It is possible to interpolate because there is a sample available - * after the resample time. It is assumed that the InputMessage frequency is 100Hz, and the frame - * frequency is 60Hz. This means the time between InputMessage samples is 10ms, and the time between - * frames is ~16ms. Resample time is frameTime - RESAMPLE_LATENCY. The resampled sample must be the - * last one in the batch to consume. - */ TEST_F(ResamplerTest, SinglePointerSingleSampleInterpolation) { MotionEvent motionEvent = InputStream{{InputSample{10ms, @@ -297,7 +321,7 @@ TEST_F(ResamplerTest, SinglePointerSingleSampleInterpolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample); + mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample); assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent, {Pointer{.id = 0, @@ -338,18 +362,13 @@ TEST_F(ResamplerTest, SinglePointerSingleSampleExtrapolation) { const MotionEvent originalMotionEvent = secondMotionEvent; - mResampler->resampleMotionEvent(11ms, secondMotionEvent, nullptr); + mResampler->resampleMotionEvent(16ms, secondMotionEvent, nullptr); assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, secondMotionEvent, {Pointer{.id = 0, .x = 2.2f, .y = 4.4f, .isResampled = true}}); - // Integrity of the whole motionEvent - // History size should increment by 1 - // Check if the resampled value is the last one - // Check if the resampleTime is correct - // Check if the PointerCoords are consistent with the other computations } TEST_F(ResamplerTest, SinglePointerMultipleSampleInterpolation) { @@ -364,7 +383,7 @@ TEST_F(ResamplerTest, SinglePointerMultipleSampleInterpolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample); + mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample); assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent, {Pointer{.id = 0, @@ -382,7 +401,7 @@ TEST_F(ResamplerTest, SinglePointerMultipleSampleExtrapolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, nullptr); + mResampler->resampleMotionEvent(16ms, motionEvent, nullptr); assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent, {Pointer{.id = 0, @@ -400,7 +419,7 @@ TEST_F(ResamplerTest, SinglePointerDeltaTooSmallExtrapolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, nullptr); + mResampler->resampleMotionEvent(16ms, motionEvent, nullptr); assertMotionEventIsNotResampled(originalMotionEvent, motionEvent); } @@ -414,7 +433,7 @@ TEST_F(ResamplerTest, SinglePointerDeltaTooLargeExtrapolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(27ms, motionEvent, nullptr); + mResampler->resampleMotionEvent(32ms, motionEvent, nullptr); assertMotionEventIsNotResampled(originalMotionEvent, motionEvent); } @@ -428,7 +447,7 @@ TEST_F(ResamplerTest, SinglePointerResampleTimeTooFarExtrapolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(43ms, motionEvent, nullptr); + mResampler->resampleMotionEvent(48ms, motionEvent, nullptr); assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent, {Pointer{.id = 0, @@ -451,7 +470,7 @@ TEST_F(ResamplerTest, MultiplePointerSingleSampleInterpolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample); + mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample); assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent, {Pointer{.x = 2.2f, .y = 2.2f, .isResampled = true}, @@ -475,7 +494,7 @@ TEST_F(ResamplerTest, MultiplePointerSingleSampleExtrapolation) { const MotionEvent originalMotionEvent = secondMotionEvent; - mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr); + mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr); assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, secondMotionEvent, {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true}, @@ -498,7 +517,7 @@ TEST_F(ResamplerTest, MultiplePointerMultipleSampleInterpolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample); + mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample); assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent, {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true}, @@ -517,7 +536,7 @@ TEST_F(ResamplerTest, MultiplePointerMultipleSampleExtrapolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr); + mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr); assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent, {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true}, @@ -539,7 +558,7 @@ TEST_F(ResamplerTest, MultiplePointerIncreaseNumPointersInterpolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample); + mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample); assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent, {Pointer{.x = 1.4f, .y = 1.4f, .isResampled = true}, @@ -560,7 +579,7 @@ TEST_F(ResamplerTest, MultiplePointerIncreaseNumPointersInterpolation) { const MotionEvent originalSecondMotionEvent = secondMotionEvent; - mResampler->resampleMotionEvent(27ms, secondMotionEvent, &secondFutureSample); + mResampler->resampleMotionEvent(32ms, secondMotionEvent, &secondFutureSample); assertMotionEventIsResampledAndCoordsNear(originalSecondMotionEvent, secondMotionEvent, {Pointer{.x = 3.8f, .y = 3.8f, .isResampled = true}, @@ -586,7 +605,7 @@ TEST_F(ResamplerTest, MultiplePointerIncreaseNumPointersExtrapolation) { const MotionEvent secondOriginalMotionEvent = secondMotionEvent; - mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr); + mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr); assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent); } @@ -606,7 +625,7 @@ TEST_F(ResamplerTest, MultiplePointerDecreaseNumPointersInterpolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample); + mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample); assertMotionEventIsNotResampled(originalMotionEvent, motionEvent); } @@ -629,7 +648,7 @@ TEST_F(ResamplerTest, MultiplePointerDecreaseNumPointersExtrapolation) { const MotionEvent secondOriginalMotionEvent = secondMotionEvent; - mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr); + mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr); assertMotionEventIsResampledAndCoordsNear(secondOriginalMotionEvent, secondMotionEvent, {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true}, @@ -650,7 +669,7 @@ TEST_F(ResamplerTest, MultiplePointerDifferentIdOrderInterpolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample); + mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample); assertMotionEventIsNotResampled(originalMotionEvent, motionEvent); } @@ -672,7 +691,7 @@ TEST_F(ResamplerTest, MultiplePointerDifferentIdOrderExtrapolation) { const MotionEvent secondOriginalMotionEvent = secondMotionEvent; - mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr); + mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr); assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent); } @@ -691,7 +710,7 @@ TEST_F(ResamplerTest, MultiplePointerDifferentIdsInterpolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample); + mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample); assertMotionEventIsNotResampled(originalMotionEvent, motionEvent); } @@ -713,7 +732,7 @@ TEST_F(ResamplerTest, MultiplePointerDifferentIdsExtrapolation) { const MotionEvent secondOriginalMotionEvent = secondMotionEvent; - mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr); + mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr); assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent); } @@ -746,7 +765,7 @@ TEST_F(ResamplerTest, MultiplePointerDifferentToolTypeInterpolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample); + mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample); assertMotionEventIsNotResampled(originalMotionEvent, motionEvent); } @@ -782,7 +801,7 @@ TEST_F(ResamplerTest, MultiplePointerDifferentToolTypeExtrapolation) { const MotionEvent secondOriginalMotionEvent = secondMotionEvent; - mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr); + mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr); assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent); } @@ -815,7 +834,7 @@ TEST_F(ResamplerTest, MultiplePointerShouldNotResampleToolTypeInterpolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr); + mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr); assertMotionEventIsNotResampled(originalMotionEvent, motionEvent); } @@ -847,7 +866,7 @@ TEST_F(ResamplerTest, MultiplePointerShouldNotResampleToolTypeExtrapolation) { const MotionEvent originalMotionEvent = motionEvent; - mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr); + mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr); assertMotionEventIsNotResampled(originalMotionEvent, motionEvent); } |