blob: b372c0b183b47ae977524b848b5d6799c6216fff [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 {
73 InputMessage message;
74 message.header.type = InputMessage::Type::MOTION;
75 message.body.motion.pointerCount = pointers.size();
76 message.body.motion.eventTime = static_cast<std::chrono::nanoseconds>(eventTime).count();
77 message.body.motion.source = AINPUT_SOURCE_CLASS_POINTER;
78 message.body.motion.downTime = 0;
Paul Ramirezcf1b06e2024-08-01 17:11:58 +000079
Paul Ramirezbe9c5442024-07-10 00:12:41 +000080 const uint32_t pointerCount = message.body.motion.pointerCount;
81 for (uint32_t i = 0; i < pointerCount; ++i) {
82 message.body.motion.pointers[i].properties.id = pointers[i].id;
83 message.body.motion.pointers[i].properties.toolType = pointers[i].toolType;
84 message.body.motion.pointers[i].coords.setAxisValue(AMOTION_EVENT_AXIS_X, pointers[i].x);
85 message.body.motion.pointers[i].coords.setAxisValue(AMOTION_EVENT_AXIS_Y, pointers[i].y);
86 message.body.motion.pointers[i].coords.isResampled = pointers[i].isResampled;
87 }
88 return message;
89}
90
91struct InputStream {
92 std::vector<InputSample> samples{};
93 int32_t action{0};
94 DeviceId deviceId{0};
95 /**
96 * Converts from InputStream to MotionEvent. Enables calling LegacyResampler methods only with
97 * the relevant data for tests.
98 */
99 operator MotionEvent() const;
100};
101
102InputStream::operator MotionEvent() const {
103 const InputSample& firstSample{*samples.begin()};
104 MotionEventBuilder motionEventBuilder =
105 MotionEventBuilder(action, AINPUT_SOURCE_CLASS_POINTER)
106 .downTime(0)
107 .eventTime(static_cast<std::chrono::nanoseconds>(firstSample.eventTime).count())
108 .deviceId(deviceId);
109 for (const Pointer& pointer : firstSample.pointers) {
110 const PointerBuilder pointerBuilder =
111 PointerBuilder(pointer.id, pointer.toolType).x(pointer.x).y(pointer.y);
112 motionEventBuilder.pointer(pointerBuilder);
113 }
114 MotionEvent motionEvent = motionEventBuilder.build();
115 const size_t numSamples = samples.size();
116 for (size_t i = 1; i < numSamples; ++i) {
117 std::vector<PointerCoords> pointersCoords{samples[i].pointers.begin(),
118 samples[i].pointers.end()};
119 motionEvent.addSample(static_cast<std::chrono::nanoseconds>(samples[i].eventTime).count(),
120 pointersCoords.data(), motionEvent.getId());
121 }
122 return motionEvent;
123}
124
125} // namespace
126
127class ResamplerTest : public testing::Test {
128protected:
129 ResamplerTest() : mResampler(std::make_unique<LegacyResampler>()) {}
130
131 ~ResamplerTest() override {}
132
133 void SetUp() override {}
134
135 void TearDown() override {}
136
137 std::unique_ptr<Resampler> mResampler;
138
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000139 /**
140 * Checks that beforeCall and afterCall are equal except for the mutated attributes by addSample
141 * member function.
142 * @param beforeCall MotionEvent before passing it to resampleMotionEvent
143 * @param afterCall MotionEvent after passing it to resampleMotionEvent
144 */
145 void assertMotionEventMetaDataDidNotMutate(const MotionEvent& beforeCall,
146 const MotionEvent& afterCall);
147
148 /**
149 * Asserts the MotionEvent is resampled by checking an increment in history size and that the
150 * resampled coordinates are near the expected ones.
151 */
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000152 void assertMotionEventIsResampledAndCoordsNear(
153 const MotionEvent& original, const MotionEvent& resampled,
154 const std::vector<PointerCoords>& expectedCoords);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000155
156 void assertMotionEventIsNotResampled(const MotionEvent& original,
157 const MotionEvent& notResampled);
158};
159
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000160void ResamplerTest::assertMotionEventMetaDataDidNotMutate(const MotionEvent& beforeCall,
161 const MotionEvent& afterCall) {
162 EXPECT_EQ(beforeCall.getDeviceId(), afterCall.getDeviceId());
163 EXPECT_EQ(beforeCall.getAction(), afterCall.getAction());
164 EXPECT_EQ(beforeCall.getActionButton(), afterCall.getActionButton());
165 EXPECT_EQ(beforeCall.getButtonState(), afterCall.getButtonState());
166 EXPECT_EQ(beforeCall.getFlags(), afterCall.getFlags());
167 EXPECT_EQ(beforeCall.getEdgeFlags(), afterCall.getEdgeFlags());
168 EXPECT_EQ(beforeCall.getClassification(), afterCall.getClassification());
169 EXPECT_EQ(beforeCall.getPointerCount(), afterCall.getPointerCount());
170 EXPECT_EQ(beforeCall.getMetaState(), afterCall.getMetaState());
171 EXPECT_EQ(beforeCall.getSource(), afterCall.getSource());
172 EXPECT_EQ(beforeCall.getXPrecision(), afterCall.getXPrecision());
173 EXPECT_EQ(beforeCall.getYPrecision(), afterCall.getYPrecision());
174 EXPECT_EQ(beforeCall.getDownTime(), afterCall.getDownTime());
175 EXPECT_EQ(beforeCall.getDisplayId(), afterCall.getDisplayId());
176}
177
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000178void ResamplerTest::assertMotionEventIsResampledAndCoordsNear(
179 const MotionEvent& original, const MotionEvent& resampled,
180 const std::vector<PointerCoords>& expectedCoords) {
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000181 assertMotionEventMetaDataDidNotMutate(original, resampled);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000182
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000183 const size_t originalSampleSize = original.getHistorySize() + 1;
184 const size_t resampledSampleSize = resampled.getHistorySize() + 1;
185 EXPECT_EQ(originalSampleSize + 1, resampledSampleSize);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000186
187 const size_t numPointers = resampled.getPointerCount();
188 const size_t beginLatestSample = resampledSampleSize - 1;
189 for (size_t i = 0; i < numPointers; ++i) {
190 SCOPED_TRACE(i);
191 EXPECT_EQ(original.getPointerId(i), resampled.getPointerId(i));
192 EXPECT_EQ(original.getToolType(i), resampled.getToolType(i));
193
194 const PointerCoords& resampledCoords =
195 resampled.getSamplePointerCoords()[beginLatestSample * numPointers + i];
196
197 EXPECT_TRUE(resampledCoords.isResampled);
198 EXPECT_NEAR(expectedCoords[i].getX(), resampledCoords.getX(), EPSILON);
199 EXPECT_NEAR(expectedCoords[i].getY(), resampledCoords.getY(), EPSILON);
200 }
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000201}
202
203void ResamplerTest::assertMotionEventIsNotResampled(const MotionEvent& original,
204 const MotionEvent& notResampled) {
205 assertMotionEventMetaDataDidNotMutate(original, notResampled);
206 const size_t originalSampleSize = original.getHistorySize() + 1;
207 const size_t notResampledSampleSize = notResampled.getHistorySize() + 1;
208 EXPECT_EQ(originalSampleSize, notResampledSampleSize);
209}
210
Paul Ramirez68ca3d12024-08-12 23:00:50 +0000211TEST_F(ResamplerTest, NonResampledAxesArePreserved) {
212 constexpr float TOUCH_MAJOR_VALUE = 1.0f;
213
214 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000215 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false}}}},
Paul Ramirez68ca3d12024-08-12 23:00:50 +0000216 AMOTION_EVENT_ACTION_MOVE};
217
218 constexpr std::chrono::nanoseconds eventTime{10ms};
219 PointerCoords pointerCoords{};
220 pointerCoords.isResampled = false;
221 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, 2.0f);
222 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, 2.0f);
223 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, TOUCH_MAJOR_VALUE);
224
225 motionEvent.addSample(eventTime.count(), &pointerCoords, motionEvent.getId());
226
227 const InputMessage futureSample =
228 InputSample{15ms, {{.id = 0, .x = 3.0f, .y = 4.0f, .isResampled = false}}};
229
230 const MotionEvent originalMotionEvent = motionEvent;
231
232 mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
233
234 EXPECT_EQ(motionEvent.getTouchMajor(0), TOUCH_MAJOR_VALUE);
235
236 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000237 {Pointer{.id = 0,
238 .x = 2.2f,
239 .y = 2.4f,
240 .isResampled = true}});
Paul Ramirez68ca3d12024-08-12 23:00:50 +0000241}
242
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000243TEST_F(ResamplerTest, SinglePointerNotEnoughDataToResample) {
244 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000245 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false}}}},
246 AMOTION_EVENT_ACTION_MOVE};
247
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000248 const MotionEvent originalMotionEvent = motionEvent;
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000249
250 mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr);
251
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000252 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
253}
254
255TEST_F(ResamplerTest, SinglePointerDifferentDeviceIdBetweenMotionEvents) {
256 MotionEvent motionFromFirstDevice =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000257 InputStream{{InputSample{4ms, {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false}}},
258 InputSample{8ms, {{.id = 0, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000259 AMOTION_EVENT_ACTION_MOVE,
260 .deviceId = 0};
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000261
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000262 mResampler->resampleMotionEvent(10ms, motionFromFirstDevice, nullptr);
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000263
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000264 MotionEvent motionFromSecondDevice =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000265 InputStream{{InputSample{11ms,
266 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000267 AMOTION_EVENT_ACTION_MOVE,
268 .deviceId = 1};
269 const MotionEvent originalMotionEvent = motionFromSecondDevice;
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000270
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000271 mResampler->resampleMotionEvent(12ms, motionFromSecondDevice, nullptr);
272 // The MotionEvent should not be resampled because the second event came from a different device
273 // than the previous event.
274 assertMotionEventIsNotResampled(originalMotionEvent, motionFromSecondDevice);
275}
276
277// Increments of 16 ms for display refresh rate
278// Increments of 6 ms for input frequency
279// Resampling latency is known to be 5 ms
280// Therefore, first resampling time will be 11 ms
281
282/**
283 * Timeline
284 * ----+----------------------+---------+---------+---------+----------
285 * 0ms 10ms 11ms 15ms 16ms
286 * DOWN MOVE | MSG |
287 * resample frame
288 * Resampling occurs at 11ms. It is possible to interpolate because there is a sample available
289 * after the resample time. It is assumed that the InputMessage frequency is 100Hz, and the frame
290 * frequency is 60Hz. This means the time between InputMessage samples is 10ms, and the time between
291 * frames is ~16ms. Resample time is frameTime - RESAMPLE_LATENCY. The resampled sample must be the
292 * last one in the batch to consume.
293 */
294TEST_F(ResamplerTest, SinglePointerSingleSampleInterpolation) {
295 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000296 InputStream{{InputSample{10ms,
297 {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000298 AMOTION_EVENT_ACTION_MOVE};
299 const InputMessage futureSample =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000300 InputSample{15ms, {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}};
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000301
302 const MotionEvent originalMotionEvent = motionEvent;
303
304 mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
305
306 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000307 {Pointer{.id = 0,
308 .x = 1.2f,
309 .y = 2.4f,
310 .isResampled = true}});
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000311}
312
313TEST_F(ResamplerTest, SinglePointerDeltaTooSmallInterpolation) {
314 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000315 InputStream{{InputSample{10ms,
316 {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000317 AMOTION_EVENT_ACTION_MOVE};
318 const InputMessage futureSample =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000319 InputSample{11ms, {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}};
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000320
321 const MotionEvent originalMotionEvent = motionEvent;
322
323 mResampler->resampleMotionEvent(10'500'000ns, motionEvent, &futureSample);
324
325 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
326}
327
328/**
329 * Tests extrapolation given two MotionEvents with a single sample.
330 */
331TEST_F(ResamplerTest, SinglePointerSingleSampleExtrapolation) {
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000332 MotionEvent firstMotionEvent =
333 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000334 AMOTION_EVENT_ACTION_MOVE};
335
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000336 mResampler->resampleMotionEvent(9ms, firstMotionEvent, nullptr);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000337
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000338 MotionEvent secondMotionEvent =
339 InputStream{{InputSample{10ms,
340 {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000341 AMOTION_EVENT_ACTION_MOVE};
342
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000343 const MotionEvent originalMotionEvent = secondMotionEvent;
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000344
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000345 mResampler->resampleMotionEvent(11ms, secondMotionEvent, nullptr);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000346
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000347 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, secondMotionEvent,
348 {Pointer{.id = 0,
349 .x = 2.2f,
350 .y = 4.4f,
351 .isResampled = true}});
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000352 // Integrity of the whole motionEvent
353 // History size should increment by 1
354 // Check if the resampled value is the last one
355 // Check if the resampleTime is correct
356 // Check if the PointerCoords are consistent with the other computations
357}
358
359TEST_F(ResamplerTest, SinglePointerMultipleSampleInterpolation) {
360 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000361 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}},
362 InputSample{10ms,
363 {{.id = 0, .x = 2.0f, .y = 3.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000364 AMOTION_EVENT_ACTION_MOVE};
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000365
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000366 const InputMessage futureSample =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000367 InputSample{15ms, {{.id = 0, .x = 3.0f, .y = 5.0f, .isResampled = false}}};
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000368
369 const MotionEvent originalMotionEvent = motionEvent;
370
371 mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
372
373 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000374 {Pointer{.id = 0,
375 .x = 2.2f,
376 .y = 3.4f,
377 .isResampled = true}});
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000378}
379
380TEST_F(ResamplerTest, SinglePointerMultipleSampleExtrapolation) {
381 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000382 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}},
383 InputSample{10ms,
384 {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000385 AMOTION_EVENT_ACTION_MOVE};
386
387 const MotionEvent originalMotionEvent = motionEvent;
388
389 mResampler->resampleMotionEvent(11ms, motionEvent, nullptr);
390
391 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000392 {Pointer{.id = 0,
393 .x = 2.2f,
394 .y = 4.4f,
395 .isResampled = true}});
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000396}
397
398TEST_F(ResamplerTest, SinglePointerDeltaTooSmallExtrapolation) {
399 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000400 InputStream{{InputSample{9ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}},
401 InputSample{10ms,
402 {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000403 AMOTION_EVENT_ACTION_MOVE};
404
405 const MotionEvent originalMotionEvent = motionEvent;
406
407 mResampler->resampleMotionEvent(11ms, motionEvent, nullptr);
408
409 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
410}
411
412TEST_F(ResamplerTest, SinglePointerDeltaTooLargeExtrapolation) {
413 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000414 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}},
415 InputSample{26ms,
416 {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000417 AMOTION_EVENT_ACTION_MOVE};
418
419 const MotionEvent originalMotionEvent = motionEvent;
420
421 mResampler->resampleMotionEvent(27ms, motionEvent, nullptr);
422
423 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
424}
425
426TEST_F(ResamplerTest, SinglePointerResampleTimeTooFarExtrapolation) {
427 MotionEvent motionEvent =
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000428 InputStream{{InputSample{5ms, {{.id = 0, .x = 1.0f, .y = 2.0f, .isResampled = false}}},
429 InputSample{25ms,
430 {{.id = 0, .x = 2.0f, .y = 4.0f, .isResampled = false}}}},
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000431 AMOTION_EVENT_ACTION_MOVE};
432
433 const MotionEvent originalMotionEvent = motionEvent;
434
435 mResampler->resampleMotionEvent(43ms, motionEvent, nullptr);
436
437 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
Paul Ramirezcf1b06e2024-08-01 17:11:58 +0000438 {Pointer{.id = 0,
439 .x = 2.4f,
440 .y = 4.8f,
441 .isResampled = true}});
442}
443
444TEST_F(ResamplerTest, MultiplePointerSingleSampleInterpolation) {
445 MotionEvent motionEvent =
446 InputStream{{InputSample{5ms,
447 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
448 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
449 AMOTION_EVENT_ACTION_MOVE};
450
451 const InputMessage futureSample =
452 InputSample{15ms,
453 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
454 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false}}};
455
456 const MotionEvent originalMotionEvent = motionEvent;
457
458 mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
459
460 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
461 {Pointer{.x = 2.2f, .y = 2.2f, .isResampled = true},
462 Pointer{.x = 3.2f, .y = 3.2f, .isResampled = true}});
463}
464
465TEST_F(ResamplerTest, MultiplePointerSingleSampleExtrapolation) {
466 MotionEvent firstMotionEvent =
467 InputStream{{InputSample{5ms,
468 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
469 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
470 AMOTION_EVENT_ACTION_MOVE};
471
472 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
473
474 MotionEvent secondMotionEvent =
475 InputStream{{InputSample{10ms,
476 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
477 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false}}}},
478 AMOTION_EVENT_ACTION_MOVE};
479
480 const MotionEvent originalMotionEvent = secondMotionEvent;
481
482 mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
483
484 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, secondMotionEvent,
485 {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
486 Pointer{.x = 4.4f, .y = 4.4f, .isResampled = true}});
487}
488
489TEST_F(ResamplerTest, MultiplePointerMultipleSampleInterpolation) {
490 MotionEvent motionEvent =
491 InputStream{{InputSample{5ms,
492 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
493 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}},
494 InputSample{10ms,
495 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
496 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false}}}},
497 AMOTION_EVENT_ACTION_MOVE};
498 const InputMessage futureSample =
499 InputSample{15ms,
500 {{.id = 0, .x = 5.0f, .y = 5.0f, .isResampled = false},
501 {.id = 1, .x = 6.0f, .y = 6.0f, .isResampled = false}}};
502
503 const MotionEvent originalMotionEvent = motionEvent;
504
505 mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
506
507 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
508 {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
509 Pointer{.x = 4.4f, .y = 4.4f, .isResampled = true}});
510}
511
512TEST_F(ResamplerTest, MultiplePointerMultipleSampleExtrapolation) {
513 MotionEvent motionEvent =
514 InputStream{{InputSample{5ms,
515 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
516 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}},
517 InputSample{10ms,
518 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
519 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false}}}},
520 AMOTION_EVENT_ACTION_MOVE};
521
522 const MotionEvent originalMotionEvent = motionEvent;
523
524 mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr);
525
526 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
527 {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
528 Pointer{.x = 4.4f, .y = 4.4f, .isResampled = true}});
529}
530
531TEST_F(ResamplerTest, MultiplePointerIncreaseNumPointersInterpolation) {
532 MotionEvent motionEvent =
533 InputStream{{InputSample{10ms,
534 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
535 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
536 AMOTION_EVENT_ACTION_MOVE};
537
538 const InputMessage futureSample =
539 InputSample{15ms,
540 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
541 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
542 {.id = 2, .x = 5.0f, .y = 5.0f, .isResampled = false}}};
543
544 const MotionEvent originalMotionEvent = motionEvent;
545
546 mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
547
548 assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
549 {Pointer{.x = 1.4f, .y = 1.4f, .isResampled = true},
550 Pointer{.x = 2.4f, .y = 2.4f, .isResampled = true}});
551
552 MotionEvent secondMotionEvent =
553 InputStream{{InputSample{25ms,
554 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
555 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
556 {.id = 2, .x = 5.0f, .y = 5.0f, .isResampled = false}}}},
557 AMOTION_EVENT_ACTION_MOVE};
558
559 const InputMessage secondFutureSample =
560 InputSample{30ms,
561 {{.id = 0, .x = 5.0f, .y = 5.0f, .isResampled = false},
562 {.id = 1, .x = 6.0f, .y = 6.0f, .isResampled = false},
563 {.id = 2, .x = 7.0f, .y = 7.0f, .isResampled = false}}};
564
565 const MotionEvent originalSecondMotionEvent = secondMotionEvent;
566
567 mResampler->resampleMotionEvent(27ms, secondMotionEvent, &secondFutureSample);
568
569 assertMotionEventIsResampledAndCoordsNear(originalSecondMotionEvent, secondMotionEvent,
570 {Pointer{.x = 3.8f, .y = 3.8f, .isResampled = true},
571 Pointer{.x = 4.8f, .y = 4.8f, .isResampled = true},
572 Pointer{.x = 5.8f, .y = 5.8f, .isResampled = true}});
573}
574
575TEST_F(ResamplerTest, MultiplePointerIncreaseNumPointersExtrapolation) {
576 MotionEvent firstMotionEvent =
577 InputStream{{InputSample{5ms,
578 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
579 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
580 AMOTION_EVENT_ACTION_MOVE};
581
582 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
583
584 MotionEvent secondMotionEvent =
585 InputStream{{InputSample{10ms,
586 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
587 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
588 {.id = 2, .x = 5.0f, .y = 5.0f, .isResampled = false}}}},
589 AMOTION_EVENT_ACTION_MOVE};
590
591 const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
592
593 mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
594
595 assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
596}
597
598TEST_F(ResamplerTest, MultiplePointerDecreaseNumPointersInterpolation) {
599 MotionEvent motionEvent =
600 InputStream{{InputSample{10ms,
601 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
602 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
603 {.id = 2, .x = 5.0f, .y = 5.0f, .isResampled = false}}}},
604 AMOTION_EVENT_ACTION_MOVE};
605
606 const InputMessage futureSample =
607 InputSample{15ms,
608 {{.id = 0, .x = 4.0f, .y = 4.0f, .isResampled = false},
609 {.id = 1, .x = 5.0f, .y = 5.0f, .isResampled = false}}};
610
611 const MotionEvent originalMotionEvent = motionEvent;
612
613 mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
614
615 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
616}
617
618TEST_F(ResamplerTest, MultiplePointerDecreaseNumPointersExtrapolation) {
619 MotionEvent firstMotionEvent =
620 InputStream{{InputSample{5ms,
621 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
622 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false},
623 {.id = 2, .x = 3.0f, .y = 3.0f, .isResampled = false}}}},
624 AMOTION_EVENT_ACTION_MOVE};
625
626 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
627
628 MotionEvent secondMotionEvent =
629 InputStream{{InputSample{10ms,
630 {{.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false},
631 {.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false}}}},
632 AMOTION_EVENT_ACTION_MOVE};
633
634 const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
635
636 mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
637
638 assertMotionEventIsResampledAndCoordsNear(secondOriginalMotionEvent, secondMotionEvent,
639 {Pointer{.x = 3.4f, .y = 3.4f, .isResampled = true},
640 Pointer{.x = 4.4f, .y = 4.4f, .isResampled = true}});
641}
642
643TEST_F(ResamplerTest, MultiplePointerDifferentIdOrderInterpolation) {
644 MotionEvent motionEvent =
645 InputStream{{InputSample{10ms,
646 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
647 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
648 AMOTION_EVENT_ACTION_MOVE};
649
650 const InputMessage futureSample =
651 InputSample{15ms,
652 {{.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
653 {.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false}}};
654
655 const MotionEvent originalMotionEvent = motionEvent;
656
657 mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
658
659 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
660}
661
662TEST_F(ResamplerTest, MultiplePointerDifferentIdOrderExtrapolation) {
663 MotionEvent firstMotionEvent =
664 InputStream{{InputSample{5ms,
665 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
666 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
667 AMOTION_EVENT_ACTION_MOVE};
668
669 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
670
671 MotionEvent secondMotionEvent =
672 InputStream{{InputSample{10ms,
673 {{.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
674 {.id = 0, .x = 3.0f, .y = 3.0f, .isResampled = false}}}},
675 AMOTION_EVENT_ACTION_MOVE};
676
677 const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
678
679 mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
680
681 assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
682}
683
684TEST_F(ResamplerTest, MultiplePointerDifferentIdsInterpolation) {
685 MotionEvent motionEvent =
686 InputStream{{InputSample{10ms,
687 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
688 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
689 AMOTION_EVENT_ACTION_MOVE};
690
691 const InputMessage futureSample =
692 InputSample{15ms,
693 {{.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
694 {.id = 2, .x = 3.0f, .y = 3.0f, .isResampled = false}}};
695
696 const MotionEvent originalMotionEvent = motionEvent;
697
698 mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
699
700 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
701}
702
703TEST_F(ResamplerTest, MultiplePointerDifferentIdsExtrapolation) {
704 MotionEvent firstMotionEvent =
705 InputStream{{InputSample{5ms,
706 {{.id = 0, .x = 1.0f, .y = 1.0f, .isResampled = false},
707 {.id = 1, .x = 2.0f, .y = 2.0f, .isResampled = false}}}},
708 AMOTION_EVENT_ACTION_MOVE};
709
710 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
711
712 MotionEvent secondMotionEvent =
713 InputStream{{InputSample{10ms,
714 {{.id = 1, .x = 4.0f, .y = 4.0f, .isResampled = false},
715 {.id = 2, .x = 3.0f, .y = 3.0f, .isResampled = false}}}},
716 AMOTION_EVENT_ACTION_MOVE};
717
718 const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
719
720 mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
721
722 assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
723}
724
725TEST_F(ResamplerTest, MultiplePointerDifferentToolTypeInterpolation) {
726 MotionEvent motionEvent = InputStream{{InputSample{10ms,
727 {{.id = 0,
728 .toolType = ToolType::FINGER,
729 .x = 1.0f,
730 .y = 1.0f,
731 .isResampled = false},
732 {.id = 1,
733 .toolType = ToolType::FINGER,
734 .x = 2.0f,
735 .y = 2.0f,
736 .isResampled = false}}}},
737 AMOTION_EVENT_ACTION_MOVE};
738
739 const InputMessage futureSample = InputSample{15ms,
740 {{.id = 0,
741 .toolType = ToolType::FINGER,
742 .x = 3.0,
743 .y = 3.0,
744 .isResampled = false},
745 {.id = 1,
746 .toolType = ToolType::STYLUS,
747 .x = 4.0,
748 .y = 4.0,
749 .isResampled = false}}};
750
751 const MotionEvent originalMotionEvent = motionEvent;
752
753 mResampler->resampleMotionEvent(11ms, motionEvent, &futureSample);
754
755 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
756}
757
758TEST_F(ResamplerTest, MultiplePointerDifferentToolTypeExtrapolation) {
759 MotionEvent firstMotionEvent = InputStream{{InputSample{5ms,
760 {{.id = 0,
761 .toolType = ToolType::FINGER,
762 .x = 1.0f,
763 .y = 1.0f,
764 .isResampled = false},
765 {.id = 1,
766 .toolType = ToolType::FINGER,
767 .x = 2.0f,
768 .y = 2.0f,
769 .isResampled = false}}}},
770 AMOTION_EVENT_ACTION_MOVE};
771
772 mResampler->resampleMotionEvent(9ms, firstMotionEvent, /*futureSample=*/nullptr);
773
774 MotionEvent secondMotionEvent = InputStream{{InputSample{10ms,
775 {{.id = 0,
776 .toolType = ToolType::FINGER,
777 .x = 1.0f,
778 .y = 1.0f,
779 .isResampled = false},
780 {.id = 1,
781 .toolType = ToolType::STYLUS,
782 .x = 2.0f,
783 .y = 2.0f,
784 .isResampled = false}}}},
785 AMOTION_EVENT_ACTION_MOVE};
786
787 const MotionEvent secondOriginalMotionEvent = secondMotionEvent;
788
789 mResampler->resampleMotionEvent(11ms, secondMotionEvent, /*futureSample=*/nullptr);
790
791 assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
792}
793
794TEST_F(ResamplerTest, MultiplePointerShouldNotResampleToolTypeInterpolation) {
795 MotionEvent motionEvent = InputStream{{InputSample{10ms,
796 {{.id = 0,
797 .toolType = ToolType::PALM,
798 .x = 1.0f,
799 .y = 1.0f,
800 .isResampled = false},
801 {.id = 1,
802 .toolType = ToolType::PALM,
803 .x = 2.0f,
804 .y = 2.0f,
805 .isResampled = false}}}},
806 AMOTION_EVENT_ACTION_MOVE};
807
808 const InputMessage futureSample = InputSample{15ms,
809 {{.id = 0,
810 .toolType = ToolType::PALM,
811 .x = 3.0,
812 .y = 3.0,
813 .isResampled = false},
814 {.id = 1,
815 .toolType = ToolType::PALM,
816 .x = 4.0,
817 .y = 4.0,
818 .isResampled = false}}};
819
820 const MotionEvent originalMotionEvent = motionEvent;
821
822 mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr);
823
824 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
825}
826
827TEST_F(ResamplerTest, MultiplePointerShouldNotResampleToolTypeExtrapolation) {
828 MotionEvent motionEvent = InputStream{{InputSample{5ms,
829 {{.id = 0,
830 .toolType = ToolType::PALM,
831 .x = 1.0f,
832 .y = 1.0f,
833 .isResampled = false},
834 {.id = 1,
835 .toolType = ToolType::PALM,
836 .x = 2.0f,
837 .y = 2.0f,
838 .isResampled = false}}},
839 InputSample{10ms,
840 {{.id = 0,
841 .toolType = ToolType::PALM,
842 .x = 3.0f,
843 .y = 3.0f,
844 .isResampled = false},
845 {.id = 1,
846 .toolType = ToolType::PALM,
847 .x = 4.0f,
848 .y = 4.0f,
849 .isResampled = false}}}},
850 AMOTION_EVENT_ACTION_MOVE};
851
852 const MotionEvent originalMotionEvent = motionEvent;
853
854 mResampler->resampleMotionEvent(11ms, motionEvent, /*futureSample=*/nullptr);
855
856 assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000857}
858} // namespace android