blob: fae8518e8762f33e29910ad5a2c6a37869278531 [file] [log] [blame]
Paul Ramirezbe9c5442024-07-10 00:12:41 +00001/**
2 * Copyright 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <input/Resampler.h>
18
19#include <gtest/gtest.h>
20
21#include <chrono>
22#include <memory>
23#include <vector>
24
25#include <input/Input.h>
26#include <input/InputEventBuilders.h>
27#include <input/InputTransport.h>
28#include <utils/Timers.h>
29
30namespace android {
31
32namespace {
33
34using namespace std::literals::chrono_literals;
35
36constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION;
37
38struct Pointer {
39 int32_t id{0};
40 ToolType toolType{ToolType::FINGER};
41 float x{0.0f};
42 float y{0.0f};
43 bool isResampled{false};
44 /**
45 * Converts from Pointer to PointerCoords. Enables calling LegacyResampler methods and
46 * assertions only with the relevant data for tests.
47 */
48 operator PointerCoords() const;
49};
50
51Pointer::operator PointerCoords() const {
52 PointerCoords pointerCoords;
53 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
54 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
55 pointerCoords.isResampled = isResampled;
56 return pointerCoords;
57}
58
59struct InputSample {
60 std::chrono::milliseconds eventTime{0};
61 std::vector<Pointer> pointers{};
Paul Ramirezcf1b06e2024-08-01 17:11:58 +000062
63 explicit InputSample(std::chrono::milliseconds eventTime, const std::vector<Pointer>& pointers)
64 : eventTime{eventTime}, pointers{pointers} {}
Paul Ramirezbe9c5442024-07-10 00:12:41 +000065 /**
66 * Converts from InputSample to InputMessage. Enables calling LegacyResampler methods only with
67 * the relevant data for tests.
68 */
69 operator InputMessage() const;
70};
71
72InputSample::operator InputMessage() const {
Paul Ramirez7dfaa322024-08-21 17:44:45 +000073 InputMessageBuilder messageBuilder =
74 InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
75 .eventTime(std::chrono::nanoseconds{eventTime}.count())
76 .source(AINPUT_SOURCE_TOUCHSCREEN)
77 .downTime(0);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +000078
Paul Ramirez7dfaa322024-08-21 17:44:45 +000079 for (const Pointer& pointer : pointers) {
80 messageBuilder.pointer(
81 PointerBuilder{pointer.id, pointer.toolType}.x(pointer.x).y(pointer.y).isResampled(
82 pointer.isResampled));
Paul Ramirezbe9c5442024-07-10 00:12:41 +000083 }
Paul Ramirez7dfaa322024-08-21 17:44:45 +000084 return messageBuilder.build();
Paul Ramirezbe9c5442024-07-10 00:12:41 +000085}
86
87struct InputStream {
88 std::vector<InputSample> samples{};
89 int32_t action{0};
Paul Ramirezbe9c5442024-07-10 00:12:41 +000090 /**
91 * Converts from InputStream to MotionEvent. Enables calling LegacyResampler methods only with
92 * the relevant data for tests.
93 */
94 operator MotionEvent() const;
95};
96
97InputStream::operator MotionEvent() const {
98 const InputSample& firstSample{*samples.begin()};
99 MotionEventBuilder motionEventBuilder =
100 MotionEventBuilder(action, AINPUT_SOURCE_CLASS_POINTER)
101 .downTime(0)
Paul Ramireze37f8342024-08-28 18:42:21 +0000102 .eventTime(
103 static_cast<std::chrono::nanoseconds>(firstSample.eventTime).count());
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000104 for (const Pointer& pointer : firstSample.pointers) {
105 const PointerBuilder pointerBuilder =
106 PointerBuilder(pointer.id, pointer.toolType).x(pointer.x).y(pointer.y);
107 motionEventBuilder.pointer(pointerBuilder);
108 }
109 MotionEvent motionEvent = motionEventBuilder.build();
110 const size_t numSamples = samples.size();
111 for (size_t i = 1; i < numSamples; ++i) {
112 std::vector<PointerCoords> pointersCoords{samples[i].pointers.begin(),
113 samples[i].pointers.end()};
114 motionEvent.addSample(static_cast<std::chrono::nanoseconds>(samples[i].eventTime).count(),
115 pointersCoords.data(), motionEvent.getId());
116 }
117 return motionEvent;
118}
119
120} // namespace
121
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000122/**
123 * The testing setup assumes an input rate of 200 Hz and a display rate of 60 Hz. This implies that
124 * input events are received every 5 milliseconds, while the display consumes batched events every
125 * ~16 milliseconds. The resampler's RESAMPLE_LATENCY constant determines the resample time, which
126 * is calculated as frameTime - RESAMPLE_LATENCY. resampleTime specifies the time used for
127 * resampling. For example, if the desired frame time consumption is ~16 milliseconds, the resample
128 * time would be ~11 milliseconds. Consequenly, the last added sample to the motion event has an
129 * event time of ~11 milliseconds. Note that there are specific scenarios where resampleMotionEvent
130 * is not called with a multiple of ~16 milliseconds. These cases are primarily for data addition
131 * or to test other functionalities of the resampler.
132 *
133 * Coordinates are calculated using linear interpolation (lerp) based on the last two available
134 * samples. Linear interpolation is defined as (a + alpha*(b - a)). Let t_b and t_a be the
135 * timestamps of samples a and b, respectively. The interpolation factor alpha is calculated as
136 * (resampleTime - t_a) / (t_b - t_a). The value of alpha determines whether the resampled
137 * coordinates are interpolated or extrapolated. If alpha falls within the semi-closed interval [0,
138 * 1), the coordinates are interpolated. If alpha is greater than or equal to 1, the coordinates are
139 * extrapolated.
140 *
141 * The timeline below depics an interpolation scenario
142 * -----------------------------------|---------|---------|---------|----------
143 * 10ms 11ms 15ms 16ms
144 * MOVE | MOVE |
145 * resampleTime frameTime
146 * Based on the timeline alpha is (11 - 10)/(15 - 10) = 1/5. Thus, coordinates are interpolated.
147 *
148 * The following timeline portrays an extrapolation scenario
149 * -------------------------|---------|---------|-------------------|----------
150 * 5ms 10ms 11ms 16ms
151 * MOVE MOVE | |
152 * resampleTime frameTime
153 * Likewise, alpha = (11 - 5)/(10 - 5) = 6/5. Hence, coordinates are extrapolated.
154 *
155 * If a motion event was resampled, the tests will check that the following conditions are satisfied
156 * to guarantee resampling correctness:
157 * - The motion event metadata must not change.
158 * - The number of samples in the motion event must only increment by 1.
159 * - The resampled values must be at the end of motion event coordinates.
160 * - The rasamples values must be near the hand calculations.
161 * - The resampled time must be the most recent one in motion event.
162 */
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000163class ResamplerTest : public testing::Test {
164protected:
165 ResamplerTest() : mResampler(std::make_unique<LegacyResampler>()) {}
166
167 ~ResamplerTest() override {}
168
169 void SetUp() override {}
170
171 void TearDown() override {}
172
173 std::unique_ptr<Resampler> mResampler;
174
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000175 /**
176 * Checks that beforeCall and afterCall are equal except for the mutated attributes by addSample
177 * member function.
178 * @param beforeCall MotionEvent before passing it to resampleMotionEvent
179 * @param afterCall MotionEvent after passing it to resampleMotionEvent
180 */
181 void assertMotionEventMetaDataDidNotMutate(const MotionEvent& beforeCall,
182 const MotionEvent& afterCall);
183
184 /**
185 * Asserts the MotionEvent is resampled by checking an increment in history size and that the
186 * resampled coordinates are near the expected ones.
187 */
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000188 void assertMotionEventIsResampledAndCoordsNear(
189 const MotionEvent& original, const MotionEvent& resampled,
190 const std::vector<PointerCoords>& expectedCoords);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000191
192 void assertMotionEventIsNotResampled(const MotionEvent& original,
193 const MotionEvent& notResampled);
194};
195
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000196void ResamplerTest::assertMotionEventMetaDataDidNotMutate(const MotionEvent& beforeCall,
197 const MotionEvent& afterCall) {
198 EXPECT_EQ(beforeCall.getDeviceId(), afterCall.getDeviceId());
199 EXPECT_EQ(beforeCall.getAction(), afterCall.getAction());
200 EXPECT_EQ(beforeCall.getActionButton(), afterCall.getActionButton());
201 EXPECT_EQ(beforeCall.getButtonState(), afterCall.getButtonState());
202 EXPECT_EQ(beforeCall.getFlags(), afterCall.getFlags());
203 EXPECT_EQ(beforeCall.getEdgeFlags(), afterCall.getEdgeFlags());
204 EXPECT_EQ(beforeCall.getClassification(), afterCall.getClassification());
205 EXPECT_EQ(beforeCall.getPointerCount(), afterCall.getPointerCount());
206 EXPECT_EQ(beforeCall.getMetaState(), afterCall.getMetaState());
207 EXPECT_EQ(beforeCall.getSource(), afterCall.getSource());
208 EXPECT_EQ(beforeCall.getXPrecision(), afterCall.getXPrecision());
209 EXPECT_EQ(beforeCall.getYPrecision(), afterCall.getYPrecision());
210 EXPECT_EQ(beforeCall.getDownTime(), afterCall.getDownTime());
211 EXPECT_EQ(beforeCall.getDisplayId(), afterCall.getDisplayId());
212}
213
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000214void ResamplerTest::assertMotionEventIsResampledAndCoordsNear(
215 const MotionEvent& original, const MotionEvent& resampled,
216 const std::vector<PointerCoords>& expectedCoords) {
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000217 assertMotionEventMetaDataDidNotMutate(original, resampled);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000218
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000219 const size_t originalSampleSize = original.getHistorySize() + 1;
220 const size_t resampledSampleSize = resampled.getHistorySize() + 1;
221 EXPECT_EQ(originalSampleSize + 1, resampledSampleSize);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000222
223 const size_t numPointers = resampled.getPointerCount();
224 const size_t beginLatestSample = resampledSampleSize - 1;
225 for (size_t i = 0; i < numPointers; ++i) {
226 SCOPED_TRACE(i);
227 EXPECT_EQ(original.getPointerId(i), resampled.getPointerId(i));
228 EXPECT_EQ(original.getToolType(i), resampled.getToolType(i));
229
230 const PointerCoords& resampledCoords =
231 resampled.getSamplePointerCoords()[beginLatestSample * numPointers + i];
232
233 EXPECT_TRUE(resampledCoords.isResampled);
234 EXPECT_NEAR(expectedCoords[i].getX(), resampledCoords.getX(), EPSILON);
235 EXPECT_NEAR(expectedCoords[i].getY(), resampledCoords.getY(), EPSILON);
236 }
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000237}
238
239void ResamplerTest::assertMotionEventIsNotResampled(const MotionEvent& original,
240 const MotionEvent& notResampled) {
241 assertMotionEventMetaDataDidNotMutate(original, notResampled);
242 const size_t originalSampleSize = original.getHistorySize() + 1;
243 const size_t notResampledSampleSize = notResampled.getHistorySize() + 1;
244 EXPECT_EQ(originalSampleSize, notResampledSampleSize);
245}
246
Paul Ramirez68ca3d12024-08-12 23:00:50 +0000247TEST_F(ResamplerTest, NonResampledAxesArePreserved) {
248 constexpr float TOUCH_MAJOR_VALUE = 1.0f;
249
250 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000251 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false}}}},
Paul Ramirez68ca3d12024-08-12 23:00:50 +0000252 AMOTION_EVENT_ACTION_MOVE};
253
254 constexpr std::chrono::nanoseconds eventTime{10ms};
255 PointerCoords pointerCoords{};
256 pointerCoords.isResampled = false;
257 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, 2.0f);
258 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, 2.0f);
259 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, TOUCH_MAJOR_VALUE);
260
261 motionEvent.addSample(eventTime.count(), &pointerCoords, motionEvent.getId());
262
263 const InputMessage futureSample =
264 InputSample{15ms, {{.id = 0, .x = 3.0f, .y = 4.0f, .isResampled = false}}};
265
266 const MotionEvent originalMotionEvent = motionEvent;
267
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000268 mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
Paul Ramirez68ca3d12024-08-12 23:00:50 +0000269
270 EXPECT_EQ(motionEvent.getTouchMajor(0), TOUCH_MAJOR_VALUE);
271
272 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000273 {Pointer{.id = 0,
274 .x = 2.2f,
275 .y = 2.4f,
276 .isResampled = true}});
Paul Ramirez68ca3d12024-08-12 23:00:50 +0000277}
278
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000279TEST_F(ResamplerTest, SinglePointerNotEnoughDataToResample) {
280 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000281 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false}}}},
282 AMOTION_EVENT_ACTION_MOVE};
283
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000284 const MotionEvent originalMotionEvent = motionEvent;
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000285
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000286 mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000287
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000288 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
289}
290
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000291TEST_F(ResamplerTest, SinglePointerSingleSampleInterpolation) {
292 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000293 InputStream{{InputSample{10ms,
294 {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000295 AMOTION_EVENT_ACTION_MOVE};
296 const InputMessage futureSample =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000297 InputSample{15ms, {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}};
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000298
299 const MotionEvent originalMotionEvent = motionEvent;
300
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000301 mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000302
303 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000304 {Pointer{.id = 0,
305 .x = 1.2f,
306 .y = 2.4f,
307 .isResampled = true}});
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000308}
309
310TEST_F(ResamplerTest, SinglePointerDeltaTooSmallInterpolation) {
311 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000312 InputStream{{InputSample{10ms,
313 {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000314 AMOTION_EVENT_ACTION_MOVE};
315 const InputMessage futureSample =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000316 InputSample{11ms, {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}};
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000317
318 const MotionEvent originalMotionEvent = motionEvent;
319
320 mResampler->resampleMotionEvent(10'500'000ns, motionEvent, &futureSample);
321
322 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
323}
324
325/**
326 * Tests extrapolation given two MotionEvents with a single sample.
327 */
328TEST_F(ResamplerTest, SinglePointerSingleSampleExtrapolation) {
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000329 MotionEvent firstMotionEvent =
330 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000331 AMOTION_EVENT_ACTION_MOVE};
332
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000333 mResampler->resampleMotionEvent(9ms, firstMotionEvent, nullptr);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000334
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000335 MotionEvent secondMotionEvent =
336 InputStream{{InputSample{10ms,
337 {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000338 AMOTION_EVENT_ACTION_MOVE};
339
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000340 const MotionEvent originalMotionEvent = secondMotionEvent;
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000341
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000342 mResampler->resampleMotionEvent(16ms, secondMotionEvent, nullptr);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000343
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000344 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, secondMotionEvent,
345 {Pointer{.id = 0,
346 .x = 2.2f,
347 .y = 4.4f,
348 .isResampled = true}});
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000349}
350
351TEST_F(ResamplerTest, SinglePointerMultipleSampleInterpolation) {
352 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000353 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}},
354 InputSample{10ms,
355 {{.id = 0, .x = 2.0f, .y = 3.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000356 AMOTION_EVENT_ACTION_MOVE};
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000357
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000358 const InputMessage futureSample =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000359 InputSample{15ms, {{.id = 0, .x = 3.0f, .y = 5.0f, .isResampled = false}}};
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000360
361 const MotionEvent originalMotionEvent = motionEvent;
362
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000363 mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000364
365 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000366 {Pointer{.id = 0,
367 .x = 2.2f,
368 .y = 3.4f,
369 .isResampled = true}});
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000370}
371
372TEST_F(ResamplerTest, SinglePointerMultipleSampleExtrapolation) {
373 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000374 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}},
375 InputSample{10ms,
376 {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000377 AMOTION_EVENT_ACTION_MOVE};
378
379 const MotionEvent originalMotionEvent = motionEvent;
380
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000381 mResampler->resampleMotionEvent(16ms, motionEvent, nullptr);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000382
383 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000384 {Pointer{.id = 0,
385 .x = 2.2f,
386 .y = 4.4f,
387 .isResampled = true}});
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000388}
389
390TEST_F(ResamplerTest, SinglePointerDeltaTooSmallExtrapolation) {
391 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000392 InputStream{{InputSample{9ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}},
393 InputSample{10ms,
394 {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000395 AMOTION_EVENT_ACTION_MOVE};
396
397 const MotionEvent originalMotionEvent = motionEvent;
398
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000399 mResampler->resampleMotionEvent(16ms, motionEvent, nullptr);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000400
401 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
402}
403
404TEST_F(ResamplerTest, SinglePointerDeltaTooLargeExtrapolation) {
405 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000406 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}},
407 InputSample{26ms,
408 {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000409 AMOTION_EVENT_ACTION_MOVE};
410
411 const MotionEvent originalMotionEvent = motionEvent;
412
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000413 mResampler->resampleMotionEvent(32ms, motionEvent, nullptr);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000414
415 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
416}
417
418TEST_F(ResamplerTest, SinglePointerResampleTimeTooFarExtrapolation) {
419 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000420 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}},
421 InputSample{25ms,
422 {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000423 AMOTION_EVENT_ACTION_MOVE};
424
425 const MotionEvent originalMotionEvent = motionEvent;
426
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000427 mResampler->resampleMotionEvent(48ms, motionEvent, nullptr);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000428
429 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000430 {Pointer{.id = 0,
431 .x = 2.4f,
432 .y = 4.8f,
433 .isResampled = true}});
434}
435
436TEST_F(ResamplerTest, MultiplePointerSingleSampleInterpolation) {
437 MotionEvent motionEvent =
438 InputStream{{InputSample{5ms,
439 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
440 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
441 AMOTION_EVENT_ACTION_MOVE};
442
443 const InputMessage futureSample =
444 InputSample{15ms,
445 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
446 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false}}};
447
448 const MotionEvent originalMotionEvent = motionEvent;
449
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000450 mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000451
452 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
453 {Pointer{.x = 2.2f, .y = 2.2f, .isResampled = true},
454 Pointer{.x = 3.2f, .y = 3.2f, .isResampled = true}});
455}
456
457TEST_F(ResamplerTest, MultiplePointerSingleSampleExtrapolation) {
458 MotionEvent firstMotionEvent =
459 InputStream{{InputSample{5ms,
460 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
461 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
462 AMOTION_EVENT_ACTION_MOVE};
463
464 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
465
466 MotionEvent secondMotionEvent =
467 InputStream{{InputSample{10ms,
468 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
469 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false}}}},
470 AMOTION_EVENT_ACTION_MOVE};
471
472 const MotionEvent originalMotionEvent = secondMotionEvent;
473
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000474 mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000475
476 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, secondMotionEvent,
477 {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
478 Pointer{.x = 4.4f, .y = 4.4f, .isResampled = true}});
479}
480
481TEST_F(ResamplerTest, MultiplePointerMultipleSampleInterpolation) {
482 MotionEvent motionEvent =
483 InputStream{{InputSample{5ms,
484 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
485 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}},
486 InputSample{10ms,
487 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
488 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false}}}},
489 AMOTION_EVENT_ACTION_MOVE};
490 const InputMessage futureSample =
491 InputSample{15ms,
492 {{.id = 0, .x = 5.0f, .y = 5.0f, .isResampled = false},
493 {.id = 1, .x = 6.0f, .y = 6.0f, .isResampled = false}}};
494
495 const MotionEvent originalMotionEvent = motionEvent;
496
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000497 mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000498
499 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
500 {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
501 Pointer{.x = 4.4f, .y = 4.4f, .isResampled = true}});
502}
503
504TEST_F(ResamplerTest, MultiplePointerMultipleSampleExtrapolation) {
505 MotionEvent motionEvent =
506 InputStream{{InputSample{5ms,
507 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
508 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}},
509 InputSample{10ms,
510 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
511 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false}}}},
512 AMOTION_EVENT_ACTION_MOVE};
513
514 const MotionEvent originalMotionEvent = motionEvent;
515
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000516 mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000517
518 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
519 {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
520 Pointer{.x = 4.4f, .y = 4.4f, .isResampled = true}});
521}
522
523TEST_F(ResamplerTest, MultiplePointerIncreaseNumPointersInterpolation) {
524 MotionEvent motionEvent =
525 InputStream{{InputSample{10ms,
526 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
527 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
528 AMOTION_EVENT_ACTION_MOVE};
529
530 const InputMessage futureSample =
531 InputSample{15ms,
532 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
533 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
534 {.id = 2, .x = 5.0f, .y = 5.0f, .isResampled = false}}};
535
536 const MotionEvent originalMotionEvent = motionEvent;
537
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000538 mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000539
540 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
541 {Pointer{.x = 1.4f, .y = 1.4f, .isResampled = true},
542 Pointer{.x = 2.4f, .y = 2.4f, .isResampled = true}});
543
544 MotionEvent secondMotionEvent =
545 InputStream{{InputSample{25ms,
546 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
547 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
548 {.id = 2, .x = 5.0f, .y = 5.0f, .isResampled = false}}}},
549 AMOTION_EVENT_ACTION_MOVE};
550
551 const InputMessage secondFutureSample =
552 InputSample{30ms,
553 {{.id = 0, .x = 5.0f, .y = 5.0f, .isResampled = false},
554 {.id = 1, .x = 6.0f, .y = 6.0f, .isResampled = false},
555 {.id = 2, .x = 7.0f, .y = 7.0f, .isResampled = false}}};
556
557 const MotionEvent originalSecondMotionEvent = secondMotionEvent;
558
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000559 mResampler->resampleMotionEvent(32ms, secondMotionEvent, &secondFutureSample);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000560
561 assertMotionEventIsResampledAndCoordsNear(originalSecondMotionEvent, secondMotionEvent,
562 {Pointer{.x = 3.8f, .y = 3.8f, .isResampled = true},
563 Pointer{.x = 4.8f, .y = 4.8f, .isResampled = true},
564 Pointer{.x = 5.8f, .y = 5.8f, .isResampled = true}});
565}
566
567TEST_F(ResamplerTest, MultiplePointerIncreaseNumPointersExtrapolation) {
568 MotionEvent firstMotionEvent =
569 InputStream{{InputSample{5ms,
570 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
571 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
572 AMOTION_EVENT_ACTION_MOVE};
573
574 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
575
576 MotionEvent secondMotionEvent =
577 InputStream{{InputSample{10ms,
578 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
579 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
580 {.id = 2, .x = 5.0f, .y = 5.0f, .isResampled = false}}}},
581 AMOTION_EVENT_ACTION_MOVE};
582
583 const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
584
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000585 mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000586
587 assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
588}
589
590TEST_F(ResamplerTest, MultiplePointerDecreaseNumPointersInterpolation) {
591 MotionEvent motionEvent =
592 InputStream{{InputSample{10ms,
593 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
594 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
595 {.id = 2, .x = 5.0f, .y = 5.0f, .isResampled = false}}}},
596 AMOTION_EVENT_ACTION_MOVE};
597
598 const InputMessage futureSample =
599 InputSample{15ms,
600 {{.id = 0, .x = 4.0f, .y = 4.0f, .isResampled = false},
601 {.id = 1, .x = 5.0f, .y = 5.0f, .isResampled = false}}};
602
603 const MotionEvent originalMotionEvent = motionEvent;
604
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000605 mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000606
607 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
608}
609
610TEST_F(ResamplerTest, MultiplePointerDecreaseNumPointersExtrapolation) {
611 MotionEvent firstMotionEvent =
612 InputStream{{InputSample{5ms,
613 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
614 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false},
615 {.id = 2, .x = 3.0f, .y = 3.0f, .isResampled = false}}}},
616 AMOTION_EVENT_ACTION_MOVE};
617
618 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
619
620 MotionEvent secondMotionEvent =
621 InputStream{{InputSample{10ms,
622 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
623 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false}}}},
624 AMOTION_EVENT_ACTION_MOVE};
625
626 const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
627
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000628 mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000629
630 assertMotionEventIsResampledAndCoordsNear(secondOriginalMotionEvent, secondMotionEvent,
631 {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
632 Pointer{.x = 4.4f, .y = 4.4f, .isResampled = true}});
633}
634
635TEST_F(ResamplerTest, MultiplePointerDifferentIdOrderInterpolation) {
636 MotionEvent motionEvent =
637 InputStream{{InputSample{10ms,
638 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
639 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
640 AMOTION_EVENT_ACTION_MOVE};
641
642 const InputMessage futureSample =
643 InputSample{15ms,
644 {{.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
645 {.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false}}};
646
647 const MotionEvent originalMotionEvent = motionEvent;
648
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000649 mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000650
651 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
652}
653
654TEST_F(ResamplerTest, MultiplePointerDifferentIdOrderExtrapolation) {
655 MotionEvent firstMotionEvent =
656 InputStream{{InputSample{5ms,
657 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
658 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
659 AMOTION_EVENT_ACTION_MOVE};
660
661 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
662
663 MotionEvent secondMotionEvent =
664 InputStream{{InputSample{10ms,
665 {{.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
666 {.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false}}}},
667 AMOTION_EVENT_ACTION_MOVE};
668
669 const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
670
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000671 mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000672
673 assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
674}
675
676TEST_F(ResamplerTest, MultiplePointerDifferentIdsInterpolation) {
677 MotionEvent motionEvent =
678 InputStream{{InputSample{10ms,
679 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
680 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
681 AMOTION_EVENT_ACTION_MOVE};
682
683 const InputMessage futureSample =
684 InputSample{15ms,
685 {{.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
686 {.id = 2, .x = 3.0f, .y = 3.0f, .isResampled = false}}};
687
688 const MotionEvent originalMotionEvent = motionEvent;
689
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000690 mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000691
692 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
693}
694
695TEST_F(ResamplerTest, MultiplePointerDifferentIdsExtrapolation) {
696 MotionEvent firstMotionEvent =
697 InputStream{{InputSample{5ms,
698 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
699 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
700 AMOTION_EVENT_ACTION_MOVE};
701
702 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
703
704 MotionEvent secondMotionEvent =
705 InputStream{{InputSample{10ms,
706 {{.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
707 {.id = 2, .x = 3.0f, .y = 3.0f, .isResampled = false}}}},
708 AMOTION_EVENT_ACTION_MOVE};
709
710 const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
711
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000712 mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000713
714 assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
715}
716
717TEST_F(ResamplerTest, MultiplePointerDifferentToolTypeInterpolation) {
718 MotionEvent motionEvent = InputStream{{InputSample{10ms,
719 {{.id = 0,
720 .toolType = ToolType::FINGER,
721 .x = 1.0f,
722 .y = 1.0f,
723 .isResampled = false},
724 {.id = 1,
725 .toolType = ToolType::FINGER,
726 .x = 2.0f,
727 .y = 2.0f,
728 .isResampled = false}}}},
729 AMOTION_EVENT_ACTION_MOVE};
730
731 const InputMessage futureSample = InputSample{15ms,
732 {{.id = 0,
733 .toolType = ToolType::FINGER,
734 .x = 3.0,
735 .y = 3.0,
736 .isResampled = false},
737 {.id = 1,
738 .toolType = ToolType::STYLUS,
739 .x = 4.0,
740 .y = 4.0,
741 .isResampled = false}}};
742
743 const MotionEvent originalMotionEvent = motionEvent;
744
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000745 mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000746
747 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
748}
749
750TEST_F(ResamplerTest, MultiplePointerDifferentToolTypeExtrapolation) {
751 MotionEvent firstMotionEvent = InputStream{{InputSample{5ms,
752 {{.id = 0,
753 .toolType = ToolType::FINGER,
754 .x = 1.0f,
755 .y = 1.0f,
756 .isResampled = false},
757 {.id = 1,
758 .toolType = ToolType::FINGER,
759 .x = 2.0f,
760 .y = 2.0f,
761 .isResampled = false}}}},
762 AMOTION_EVENT_ACTION_MOVE};
763
764 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
765
766 MotionEvent secondMotionEvent = InputStream{{InputSample{10ms,
767 {{.id = 0,
768 .toolType = ToolType::FINGER,
769 .x = 1.0f,
770 .y = 1.0f,
771 .isResampled = false},
772 {.id = 1,
773 .toolType = ToolType::STYLUS,
774 .x = 2.0f,
775 .y = 2.0f,
776 .isResampled = false}}}},
777 AMOTION_EVENT_ACTION_MOVE};
778
779 const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
780
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000781 mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000782
783 assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
784}
785
786TEST_F(ResamplerTest, MultiplePointerShouldNotResampleToolTypeInterpolation) {
787 MotionEvent motionEvent = InputStream{{InputSample{10ms,
788 {{.id = 0,
789 .toolType = ToolType::PALM,
790 .x = 1.0f,
791 .y = 1.0f,
792 .isResampled = false},
793 {.id = 1,
794 .toolType = ToolType::PALM,
795 .x = 2.0f,
796 .y = 2.0f,
797 .isResampled = false}}}},
798 AMOTION_EVENT_ACTION_MOVE};
799
800 const InputMessage futureSample = InputSample{15ms,
801 {{.id = 0,
802 .toolType = ToolType::PALM,
803 .x = 3.0,
804 .y = 3.0,
805 .isResampled = false},
806 {.id = 1,
807 .toolType = ToolType::PALM,
808 .x = 4.0,
809 .y = 4.0,
810 .isResampled = false}}};
811
812 const MotionEvent originalMotionEvent = motionEvent;
813
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000814 mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000815
816 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
817}
818
819TEST_F(ResamplerTest, MultiplePointerShouldNotResampleToolTypeExtrapolation) {
820 MotionEvent motionEvent = InputStream{{InputSample{5ms,
821 {{.id = 0,
822 .toolType = ToolType::PALM,
823 .x = 1.0f,
824 .y = 1.0f,
825 .isResampled = false},
826 {.id = 1,
827 .toolType = ToolType::PALM,
828 .x = 2.0f,
829 .y = 2.0f,
830 .isResampled = false}}},
831 InputSample{10ms,
832 {{.id = 0,
833 .toolType = ToolType::PALM,
834 .x = 3.0f,
835 .y = 3.0f,
836 .isResampled = false},
837 {.id = 1,
838 .toolType = ToolType::PALM,
839 .x = 4.0f,
840 .y = 4.0f,
841 .isResampled = false}}}},
842 AMOTION_EVENT_ACTION_MOVE};
843
844 const MotionEvent originalMotionEvent = motionEvent;
845
Paul Ramirez6affbdb2024-09-11 22:20:26 +0000846 mResampler->resampleMotionEvent(16ms, motionEvent, /*futureSample=*/nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000847
848 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000849}
850} // namespace android