blob: cbb332ed7f7b540bcc4d1dbbc5328a384596fd4b [file] [log] [blame]
Paul Ramireze2bb1872024-08-12 20:21:13 +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/InputConsumerNoResampling.h>
18
Paul Ramireze37f8342024-08-28 18:42:21 +000019#include <gtest/gtest.h>
20
21#include <chrono>
Paul Ramireze2bb1872024-08-12 20:21:13 +000022#include <memory>
23#include <optional>
Paul Ramireze2bb1872024-08-12 20:21:13 +000024
Paul Ramirez00cf5d02024-09-05 17:10:12 +000025#include <TestEventMatchers.h>
Paul Ramireze2bb1872024-08-12 20:21:13 +000026#include <TestInputChannel.h>
Paul Ramireze2bb1872024-08-12 20:21:13 +000027#include <android-base/logging.h>
Paul Ramirez00cf5d02024-09-05 17:10:12 +000028#include <gmock/gmock.h>
Paul Ramireze2bb1872024-08-12 20:21:13 +000029#include <gtest/gtest.h>
30#include <input/BlockingQueue.h>
Paul Ramireze37f8342024-08-28 18:42:21 +000031#include <input/Input.h>
Paul Ramireze2bb1872024-08-12 20:21:13 +000032#include <input/InputEventBuilders.h>
Paul Ramireze37f8342024-08-28 18:42:21 +000033#include <input/Resampler.h>
Paul Ramirez87f1c012024-09-18 18:23:14 +000034#include <utils/Looper.h>
Paul Ramireze2bb1872024-08-12 20:21:13 +000035#include <utils/StrongPointer.h>
36
37namespace android {
38
Paul Ramirezcd7488c2024-09-13 23:01:12 +000039namespace {
40
41using std::chrono::nanoseconds;
42
Paul Ramirez00cf5d02024-09-05 17:10:12 +000043using ::testing::AllOf;
44using ::testing::Matcher;
Paul Ramirez00cf5d02024-09-05 17:10:12 +000045
Paul Ramireze37f8342024-08-28 18:42:21 +000046struct Pointer {
47 int32_t id{0};
48 ToolType toolType{ToolType::FINGER};
49 float x{0.0f};
50 float y{0.0f};
51 bool isResampled{false};
52
53 PointerBuilder asPointerBuilder() const {
54 return PointerBuilder{id, toolType}.x(x).y(y).isResampled(isResampled);
55 }
56};
Paul Ramirezcd7488c2024-09-13 23:01:12 +000057} // namespace
58
Paul Ramireze2bb1872024-08-12 20:21:13 +000059class InputConsumerTest : public testing::Test, public InputConsumerCallbacks {
60protected:
61 InputConsumerTest()
62 : mClientTestChannel{std::make_shared<TestInputChannel>("TestChannel")},
Paul Ramirez87f1c012024-09-18 18:23:14 +000063 mLooper{sp<Looper>::make(/*allowNonCallbacks=*/false)} {
64 Looper::setForThread(mLooper);
Paul Ramireze37f8342024-08-28 18:42:21 +000065 mConsumer = std::make_unique<
66 InputConsumerNoResampling>(mClientTestChannel, mLooper, *this,
67 []() { return std::make_unique<LegacyResampler>(); });
Paul Ramireze2bb1872024-08-12 20:21:13 +000068 }
69
Paul Ramirez87f1c012024-09-18 18:23:14 +000070 void invokeLooperCallback() const {
71 sp<LooperCallback> callback;
72 ASSERT_TRUE(mLooper->getFdStateDebug(mClientTestChannel->getFd(), /*ident=*/nullptr,
73 /*events=*/nullptr, &callback, /*data=*/nullptr));
74 callback->handleEvent(mClientTestChannel->getFd(), ALOOPER_EVENT_INPUT, /*data=*/nullptr);
75 }
76
Paul Ramirez00cf5d02024-09-05 17:10:12 +000077 void assertOnBatchedInputEventPendingWasCalled() {
78 ASSERT_GT(mOnBatchedInputEventPendingInvocationCount, 0UL)
79 << "onBatchedInputEventPending has not been called.";
80 --mOnBatchedInputEventPendingInvocationCount;
81 }
82
83 void assertReceivedMotionEvent(const Matcher<MotionEvent>& matcher) {
84 std::unique_ptr<MotionEvent> motionEvent = mMotionEvents.pop();
85 ASSERT_NE(motionEvent, nullptr);
86 EXPECT_THAT(*motionEvent, matcher);
87 }
Paul Ramireze2bb1872024-08-12 20:21:13 +000088
Paul Ramireze37f8342024-08-28 18:42:21 +000089 InputMessage nextPointerMessage(std::chrono::nanoseconds eventTime, DeviceId deviceId,
90 int32_t action, const Pointer& pointer);
91
Paul Ramireze2bb1872024-08-12 20:21:13 +000092 std::shared_ptr<TestInputChannel> mClientTestChannel;
Paul Ramirez87f1c012024-09-18 18:23:14 +000093 sp<Looper> mLooper;
Paul Ramireze2bb1872024-08-12 20:21:13 +000094 std::unique_ptr<InputConsumerNoResampling> mConsumer;
95
96 BlockingQueue<std::unique_ptr<KeyEvent>> mKeyEvents;
97 BlockingQueue<std::unique_ptr<MotionEvent>> mMotionEvents;
98 BlockingQueue<std::unique_ptr<FocusEvent>> mFocusEvents;
99 BlockingQueue<std::unique_ptr<CaptureEvent>> mCaptureEvents;
100 BlockingQueue<std::unique_ptr<DragEvent>> mDragEvents;
101 BlockingQueue<std::unique_ptr<TouchModeEvent>> mTouchModeEvents;
102
103private:
Paul Ramireze37f8342024-08-28 18:42:21 +0000104 uint32_t mLastSeq{0};
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000105 size_t mOnBatchedInputEventPendingInvocationCount{0};
Paul Ramireze2bb1872024-08-12 20:21:13 +0000106
107 // InputConsumerCallbacks interface
108 void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) override {
109 mKeyEvents.push(std::move(event));
110 mConsumer->finishInputEvent(seq, true);
111 }
112 void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) override {
113 mMotionEvents.push(std::move(event));
114 mConsumer->finishInputEvent(seq, true);
115 }
116 void onBatchedInputEventPending(int32_t pendingBatchSource) override {
117 if (!mConsumer->probablyHasInput()) {
118 ADD_FAILURE() << "should deterministically have input because there is a batch";
119 }
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000120 ++mOnBatchedInputEventPendingInvocationCount;
Paul Ramireze2bb1872024-08-12 20:21:13 +0000121 };
122 void onFocusEvent(std::unique_ptr<FocusEvent> event, uint32_t seq) override {
123 mFocusEvents.push(std::move(event));
124 mConsumer->finishInputEvent(seq, true);
125 };
126 void onCaptureEvent(std::unique_ptr<CaptureEvent> event, uint32_t seq) override {
127 mCaptureEvents.push(std::move(event));
128 mConsumer->finishInputEvent(seq, true);
129 };
130 void onDragEvent(std::unique_ptr<DragEvent> event, uint32_t seq) override {
131 mDragEvents.push(std::move(event));
132 mConsumer->finishInputEvent(seq, true);
133 }
134 void onTouchModeEvent(std::unique_ptr<TouchModeEvent> event, uint32_t seq) override {
135 mTouchModeEvents.push(std::move(event));
136 mConsumer->finishInputEvent(seq, true);
137 };
138};
139
Paul Ramireze37f8342024-08-28 18:42:21 +0000140InputMessage InputConsumerTest::nextPointerMessage(std::chrono::nanoseconds eventTime,
141 DeviceId deviceId, int32_t action,
142 const Pointer& pointer) {
143 ++mLastSeq;
144 return InputMessageBuilder{InputMessage::Type::MOTION, mLastSeq}
145 .eventTime(eventTime.count())
146 .deviceId(deviceId)
147 .source(AINPUT_SOURCE_TOUCHSCREEN)
148 .action(action)
149 .pointer(pointer.asPointerBuilder())
150 .build();
151}
152
Paul Ramireze2bb1872024-08-12 20:21:13 +0000153TEST_F(InputConsumerTest, MessageStreamBatchedInMotionEvent) {
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000154 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
155 .eventTime(nanoseconds{0ms}.count())
156 .action(AMOTION_EVENT_ACTION_DOWN)
157 .build());
158 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}
159 .eventTime(nanoseconds{5ms}.count())
160 .action(AMOTION_EVENT_ACTION_MOVE)
161 .build());
162 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/2}
163 .eventTime(nanoseconds{10ms}.count())
164 .action(AMOTION_EVENT_ACTION_MOVE)
165 .build());
Paul Ramireze2bb1872024-08-12 20:21:13 +0000166
167 mClientTestChannel->assertNoSentMessages();
168
Paul Ramirez87f1c012024-09-18 18:23:14 +0000169 invokeLooperCallback();
Paul Ramireze2bb1872024-08-12 20:21:13 +0000170
171 assertOnBatchedInputEventPendingWasCalled();
172
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000173 mConsumer->consumeBatchedInputEvents(/*frameTime=*/std::nullopt);
Paul Ramireze2bb1872024-08-12 20:21:13 +0000174
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000175 std::unique_ptr<MotionEvent> downMotionEvent = mMotionEvents.pop();
176 ASSERT_NE(downMotionEvent, nullptr);
177
178 std::unique_ptr<MotionEvent> moveMotionEvent = mMotionEvents.pop();
179 ASSERT_NE(moveMotionEvent, nullptr);
180 EXPECT_EQ(moveMotionEvent->getHistorySize() + 1, 3UL);
Paul Ramireze2bb1872024-08-12 20:21:13 +0000181
182 mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
183 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
184 mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000185}
Paul Ramireze2bb1872024-08-12 20:21:13 +0000186
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000187TEST_F(InputConsumerTest, LastBatchedSampleIsLessThanResampleTime) {
188 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
189 .eventTime(nanoseconds{0ms}.count())
190 .action(AMOTION_EVENT_ACTION_DOWN)
191 .build());
192 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}
193 .eventTime(nanoseconds{5ms}.count())
194 .action(AMOTION_EVENT_ACTION_MOVE)
195 .build());
196 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/2}
197 .eventTime(nanoseconds{10ms}.count())
198 .action(AMOTION_EVENT_ACTION_MOVE)
199 .build());
200 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/3}
201 .eventTime(nanoseconds{15ms}.count())
202 .action(AMOTION_EVENT_ACTION_MOVE)
203 .build());
204
205 mClientTestChannel->assertNoSentMessages();
206
Paul Ramirez87f1c012024-09-18 18:23:14 +0000207 invokeLooperCallback();
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000208
209 assertOnBatchedInputEventPendingWasCalled();
210
211 mConsumer->consumeBatchedInputEvents(16'000'000 /*ns*/);
212
213 std::unique_ptr<MotionEvent> downMotionEvent = mMotionEvents.pop();
214 ASSERT_NE(downMotionEvent, nullptr);
215
216 std::unique_ptr<MotionEvent> moveMotionEvent = mMotionEvents.pop();
217 ASSERT_NE(moveMotionEvent, nullptr);
218 const size_t numSamples = moveMotionEvent->getHistorySize() + 1;
219 EXPECT_LT(moveMotionEvent->getHistoricalEventTime(numSamples - 2),
220 moveMotionEvent->getEventTime());
221
222 // Consume all remaining events before ending the test. Otherwise, the smart pointer that owns
223 // consumer is set to null before destroying consumer. This leads to a member function call on a
224 // null object.
225 // TODO(b/332613662): Remove this workaround.
226 mConsumer->consumeBatchedInputEvents(std::nullopt);
227
228 mClientTestChannel->assertFinishMessage(/*seq=*/0, true);
229 mClientTestChannel->assertFinishMessage(/*seq=*/1, true);
230 mClientTestChannel->assertFinishMessage(/*seq=*/2, true);
231 mClientTestChannel->assertFinishMessage(/*seq=*/3, true);
Paul Ramireze2bb1872024-08-12 20:21:13 +0000232}
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000233
234TEST_F(InputConsumerTest, BatchedEventsMultiDeviceConsumption) {
235 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
236 .deviceId(0)
237 .action(AMOTION_EVENT_ACTION_DOWN)
238 .build());
239
Paul Ramirez87f1c012024-09-18 18:23:14 +0000240 invokeLooperCallback();
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000241 assertReceivedMotionEvent(AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
242
243 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}
244 .deviceId(0)
245 .action(AMOTION_EVENT_ACTION_MOVE)
246 .build());
247 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/2}
248 .deviceId(0)
249 .action(AMOTION_EVENT_ACTION_MOVE)
250 .build());
251 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/3}
252 .deviceId(0)
253 .action(AMOTION_EVENT_ACTION_MOVE)
254 .build());
255
256 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/4}
257 .deviceId(1)
258 .action(AMOTION_EVENT_ACTION_DOWN)
259 .build());
260
Paul Ramirez87f1c012024-09-18 18:23:14 +0000261 invokeLooperCallback();
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000262 assertReceivedMotionEvent(AllOf(WithDeviceId(1), WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
263
264 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/5}
265 .deviceId(0)
266 .action(AMOTION_EVENT_ACTION_UP)
267 .build());
268
Paul Ramirez87f1c012024-09-18 18:23:14 +0000269 invokeLooperCallback();
Paul Ramireze37f8342024-08-28 18:42:21 +0000270 assertReceivedMotionEvent(AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000271
272 mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
273 mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
274 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
275 mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
276 mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
277}
Paul Ramireze37f8342024-08-28 18:42:21 +0000278
279/**
280 * The test supposes a 60Hz Vsync rate and a 200Hz input rate. The InputMessages are intertwined as
281 * in a real use cases. The test's two devices should be resampled independently. Moreover, the
282 * InputMessage stream layout for the test is:
283 *
284 * DOWN(0, 0ms)
285 * MOVE(0, 5ms)
286 * MOVE(0, 10ms)
287 * DOWN(1, 15ms)
288 *
289 * CONSUME(16ms)
290 *
291 * MOVE(1, 20ms)
292 * MOVE(1, 25ms)
293 * MOVE(0, 30ms)
294 *
295 * CONSUME(32ms)
296 *
297 * MOVE(0, 35ms)
298 * UP(1, 40ms)
299 * UP(0, 45ms)
300 *
301 * CONSUME(48ms)
302 *
303 * The first field is device ID, and the second field is event time.
304 */
305TEST_F(InputConsumerTest, MultiDeviceResampling) {
306 mClientTestChannel->enqueueMessage(nextPointerMessage(0ms, /*deviceId=*/0,
307 AMOTION_EVENT_ACTION_DOWN,
308 Pointer{.x = 0, .y = 0}));
309
310 mClientTestChannel->assertNoSentMessages();
311
312 invokeLooperCallback();
313 assertReceivedMotionEvent(AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
314 WithSampleCount(1)));
315
316 mClientTestChannel->enqueueMessage(nextPointerMessage(5ms, /*deviceId=*/0,
317 AMOTION_EVENT_ACTION_MOVE,
318 Pointer{.x = 1.0f, .y = 2.0f}));
319 mClientTestChannel->enqueueMessage(nextPointerMessage(10ms, /*deviceId=*/0,
320 AMOTION_EVENT_ACTION_MOVE,
321 Pointer{.x = 2.0f, .y = 4.0f}));
322 mClientTestChannel->enqueueMessage(nextPointerMessage(15ms, /*deviceId=*/1,
323 AMOTION_EVENT_ACTION_DOWN,
324 Pointer{.x = 10.0f, .y = 10.0f}));
325
326 invokeLooperCallback();
327 mConsumer->consumeBatchedInputEvents(16'000'000 /*ns*/);
328
329 assertReceivedMotionEvent(AllOf(WithDeviceId(1), WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
330 WithSampleCount(1)));
331 assertReceivedMotionEvent(
332 AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithSampleCount(3),
333 WithSample(/*sampleIndex=*/2,
334 Sample{11ms,
335 {PointerArgs{.x = 2.2f, .y = 4.4f, .isResampled = true}}})));
336
337 mClientTestChannel->enqueueMessage(nextPointerMessage(20ms, /*deviceId=*/1,
338 AMOTION_EVENT_ACTION_MOVE,
339 Pointer{.x = 11.0f, .y = 12.0f}));
340 mClientTestChannel->enqueueMessage(nextPointerMessage(25ms, /*deviceId=*/1,
341 AMOTION_EVENT_ACTION_MOVE,
342 Pointer{.x = 12.0f, .y = 14.0f}));
343 mClientTestChannel->enqueueMessage(nextPointerMessage(30ms, /*deviceId=*/0,
344 AMOTION_EVENT_ACTION_MOVE,
345 Pointer{.x = 5.0f, .y = 6.0f}));
346
347 invokeLooperCallback();
348 assertOnBatchedInputEventPendingWasCalled();
349 mConsumer->consumeBatchedInputEvents(32'000'000 /*ns*/);
350
351 assertReceivedMotionEvent(
352 AllOf(WithDeviceId(1), WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithSampleCount(3),
353 WithSample(/*sampleIndex=*/2,
354 Sample{27ms,
355 {PointerArgs{.x = 12.4f, .y = 14.8f, .isResampled = true}}})));
356
357 mClientTestChannel->enqueueMessage(nextPointerMessage(35ms, /*deviceId=*/0,
358 AMOTION_EVENT_ACTION_MOVE,
359 Pointer{.x = 8.0f, .y = 9.0f}));
360 mClientTestChannel->enqueueMessage(nextPointerMessage(40ms, /*deviceId=*/1,
361 AMOTION_EVENT_ACTION_UP,
362 Pointer{.x = 12.0f, .y = 14.0f}));
363 mClientTestChannel->enqueueMessage(nextPointerMessage(45ms, /*deviceId=*/0,
364 AMOTION_EVENT_ACTION_UP,
365 Pointer{.x = 8.0f, .y = 9.0f}));
366
367 invokeLooperCallback();
368 mConsumer->consumeBatchedInputEvents(48'000'000 /*ns*/);
369
370 assertReceivedMotionEvent(
371 AllOf(WithDeviceId(1), WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSampleCount(1)));
372
373 assertReceivedMotionEvent(
374 AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithSampleCount(3),
375 WithSample(/*sampleIndex=*/2,
376 Sample{37'500'000ns,
377 {PointerArgs{.x = 9.5f, .y = 10.5f, .isResampled = true}}})));
378
379 assertReceivedMotionEvent(
380 AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSampleCount(1)));
381
382 // The sequence order is based on the expected consumption. Each sequence number corresponds to
383 // one of the previously enqueued messages.
384 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
385 mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
386 mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
387 mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
388 mClientTestChannel->assertFinishMessage(/*seq=*/5, /*handled=*/true);
389 mClientTestChannel->assertFinishMessage(/*seq=*/6, /*handled=*/true);
390 mClientTestChannel->assertFinishMessage(/*seq=*/9, /*handled=*/true);
391 mClientTestChannel->assertFinishMessage(/*seq=*/7, /*handled=*/true);
392 mClientTestChannel->assertFinishMessage(/*seq=*/8, /*handled=*/true);
393 mClientTestChannel->assertFinishMessage(/*seq=*/10, /*handled=*/true);
394}
Paul Ramireze2bb1872024-08-12 20:21:13 +0000395} // namespace android