blob: d708316236272b9148299a23fcc55a7a4d59d5f8 [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
19#include <memory>
20#include <optional>
Paul Ramireze2bb1872024-08-12 20:21:13 +000021
Paul Ramirez00cf5d02024-09-05 17:10:12 +000022#include <TestEventMatchers.h>
Paul Ramireze2bb1872024-08-12 20:21:13 +000023#include <TestInputChannel.h>
Paul Ramireze2bb1872024-08-12 20:21:13 +000024#include <android-base/logging.h>
Paul Ramirez00cf5d02024-09-05 17:10:12 +000025#include <gmock/gmock.h>
Paul Ramireze2bb1872024-08-12 20:21:13 +000026#include <gtest/gtest.h>
27#include <input/BlockingQueue.h>
28#include <input/InputEventBuilders.h>
Paul Ramirez87f1c012024-09-18 18:23:14 +000029#include <utils/Looper.h>
Paul Ramireze2bb1872024-08-12 20:21:13 +000030#include <utils/StrongPointer.h>
31
32namespace android {
33
Paul Ramirezcd7488c2024-09-13 23:01:12 +000034namespace {
35
36using std::chrono::nanoseconds;
37
Paul Ramirez00cf5d02024-09-05 17:10:12 +000038using ::testing::AllOf;
39using ::testing::Matcher;
40using ::testing::Not;
41
Paul Ramirezcd7488c2024-09-13 23:01:12 +000042} // namespace
43
Paul Ramireze2bb1872024-08-12 20:21:13 +000044class InputConsumerTest : public testing::Test, public InputConsumerCallbacks {
45protected:
46 InputConsumerTest()
47 : mClientTestChannel{std::make_shared<TestInputChannel>("TestChannel")},
Paul Ramirez87f1c012024-09-18 18:23:14 +000048 mLooper{sp<Looper>::make(/*allowNonCallbacks=*/false)} {
49 Looper::setForThread(mLooper);
Paul Ramirezcd7488c2024-09-13 23:01:12 +000050 mConsumer =
Paul Ramirez87f1c012024-09-18 18:23:14 +000051 std::make_unique<InputConsumerNoResampling>(mClientTestChannel, mLooper, *this,
Paul Ramirezcd7488c2024-09-13 23:01:12 +000052 std::make_unique<LegacyResampler>());
Paul Ramireze2bb1872024-08-12 20:21:13 +000053 }
54
Paul Ramirez87f1c012024-09-18 18:23:14 +000055 void invokeLooperCallback() const {
56 sp<LooperCallback> callback;
57 ASSERT_TRUE(mLooper->getFdStateDebug(mClientTestChannel->getFd(), /*ident=*/nullptr,
58 /*events=*/nullptr, &callback, /*data=*/nullptr));
59 callback->handleEvent(mClientTestChannel->getFd(), ALOOPER_EVENT_INPUT, /*data=*/nullptr);
60 }
61
Paul Ramirez00cf5d02024-09-05 17:10:12 +000062 void assertOnBatchedInputEventPendingWasCalled() {
63 ASSERT_GT(mOnBatchedInputEventPendingInvocationCount, 0UL)
64 << "onBatchedInputEventPending has not been called.";
65 --mOnBatchedInputEventPendingInvocationCount;
66 }
67
68 void assertReceivedMotionEvent(const Matcher<MotionEvent>& matcher) {
69 std::unique_ptr<MotionEvent> motionEvent = mMotionEvents.pop();
70 ASSERT_NE(motionEvent, nullptr);
71 EXPECT_THAT(*motionEvent, matcher);
72 }
Paul Ramireze2bb1872024-08-12 20:21:13 +000073
74 std::shared_ptr<TestInputChannel> mClientTestChannel;
Paul Ramirez87f1c012024-09-18 18:23:14 +000075 sp<Looper> mLooper;
Paul Ramireze2bb1872024-08-12 20:21:13 +000076 std::unique_ptr<InputConsumerNoResampling> mConsumer;
77
78 BlockingQueue<std::unique_ptr<KeyEvent>> mKeyEvents;
79 BlockingQueue<std::unique_ptr<MotionEvent>> mMotionEvents;
80 BlockingQueue<std::unique_ptr<FocusEvent>> mFocusEvents;
81 BlockingQueue<std::unique_ptr<CaptureEvent>> mCaptureEvents;
82 BlockingQueue<std::unique_ptr<DragEvent>> mDragEvents;
83 BlockingQueue<std::unique_ptr<TouchModeEvent>> mTouchModeEvents;
84
85private:
Paul Ramirezcd7488c2024-09-13 23:01:12 +000086 size_t mOnBatchedInputEventPendingInvocationCount{0};
Paul Ramireze2bb1872024-08-12 20:21:13 +000087
88 // InputConsumerCallbacks interface
89 void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) override {
90 mKeyEvents.push(std::move(event));
91 mConsumer->finishInputEvent(seq, true);
92 }
93 void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) override {
94 mMotionEvents.push(std::move(event));
95 mConsumer->finishInputEvent(seq, true);
96 }
97 void onBatchedInputEventPending(int32_t pendingBatchSource) override {
98 if (!mConsumer->probablyHasInput()) {
99 ADD_FAILURE() << "should deterministically have input because there is a batch";
100 }
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000101 ++mOnBatchedInputEventPendingInvocationCount;
Paul Ramireze2bb1872024-08-12 20:21:13 +0000102 };
103 void onFocusEvent(std::unique_ptr<FocusEvent> event, uint32_t seq) override {
104 mFocusEvents.push(std::move(event));
105 mConsumer->finishInputEvent(seq, true);
106 };
107 void onCaptureEvent(std::unique_ptr<CaptureEvent> event, uint32_t seq) override {
108 mCaptureEvents.push(std::move(event));
109 mConsumer->finishInputEvent(seq, true);
110 };
111 void onDragEvent(std::unique_ptr<DragEvent> event, uint32_t seq) override {
112 mDragEvents.push(std::move(event));
113 mConsumer->finishInputEvent(seq, true);
114 }
115 void onTouchModeEvent(std::unique_ptr<TouchModeEvent> event, uint32_t seq) override {
116 mTouchModeEvents.push(std::move(event));
117 mConsumer->finishInputEvent(seq, true);
118 };
119};
120
Paul Ramireze2bb1872024-08-12 20:21:13 +0000121TEST_F(InputConsumerTest, MessageStreamBatchedInMotionEvent) {
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000122 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
123 .eventTime(nanoseconds{0ms}.count())
124 .action(AMOTION_EVENT_ACTION_DOWN)
125 .build());
126 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}
127 .eventTime(nanoseconds{5ms}.count())
128 .action(AMOTION_EVENT_ACTION_MOVE)
129 .build());
130 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/2}
131 .eventTime(nanoseconds{10ms}.count())
132 .action(AMOTION_EVENT_ACTION_MOVE)
133 .build());
Paul Ramireze2bb1872024-08-12 20:21:13 +0000134
135 mClientTestChannel->assertNoSentMessages();
136
Paul Ramirez87f1c012024-09-18 18:23:14 +0000137 invokeLooperCallback();
Paul Ramireze2bb1872024-08-12 20:21:13 +0000138
139 assertOnBatchedInputEventPendingWasCalled();
140
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000141 mConsumer->consumeBatchedInputEvents(/*frameTime=*/std::nullopt);
Paul Ramireze2bb1872024-08-12 20:21:13 +0000142
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000143 std::unique_ptr<MotionEvent> downMotionEvent = mMotionEvents.pop();
144 ASSERT_NE(downMotionEvent, nullptr);
145
146 std::unique_ptr<MotionEvent> moveMotionEvent = mMotionEvents.pop();
147 ASSERT_NE(moveMotionEvent, nullptr);
148 EXPECT_EQ(moveMotionEvent->getHistorySize() + 1, 3UL);
Paul Ramireze2bb1872024-08-12 20:21:13 +0000149
150 mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
151 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
152 mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000153}
Paul Ramireze2bb1872024-08-12 20:21:13 +0000154
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000155TEST_F(InputConsumerTest, LastBatchedSampleIsLessThanResampleTime) {
156 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
157 .eventTime(nanoseconds{0ms}.count())
158 .action(AMOTION_EVENT_ACTION_DOWN)
159 .build());
160 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}
161 .eventTime(nanoseconds{5ms}.count())
162 .action(AMOTION_EVENT_ACTION_MOVE)
163 .build());
164 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/2}
165 .eventTime(nanoseconds{10ms}.count())
166 .action(AMOTION_EVENT_ACTION_MOVE)
167 .build());
168 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/3}
169 .eventTime(nanoseconds{15ms}.count())
170 .action(AMOTION_EVENT_ACTION_MOVE)
171 .build());
172
173 mClientTestChannel->assertNoSentMessages();
174
Paul Ramirez87f1c012024-09-18 18:23:14 +0000175 invokeLooperCallback();
Paul Ramirezcd7488c2024-09-13 23:01:12 +0000176
177 assertOnBatchedInputEventPendingWasCalled();
178
179 mConsumer->consumeBatchedInputEvents(16'000'000 /*ns*/);
180
181 std::unique_ptr<MotionEvent> downMotionEvent = mMotionEvents.pop();
182 ASSERT_NE(downMotionEvent, nullptr);
183
184 std::unique_ptr<MotionEvent> moveMotionEvent = mMotionEvents.pop();
185 ASSERT_NE(moveMotionEvent, nullptr);
186 const size_t numSamples = moveMotionEvent->getHistorySize() + 1;
187 EXPECT_LT(moveMotionEvent->getHistoricalEventTime(numSamples - 2),
188 moveMotionEvent->getEventTime());
189
190 // Consume all remaining events before ending the test. Otherwise, the smart pointer that owns
191 // consumer is set to null before destroying consumer. This leads to a member function call on a
192 // null object.
193 // TODO(b/332613662): Remove this workaround.
194 mConsumer->consumeBatchedInputEvents(std::nullopt);
195
196 mClientTestChannel->assertFinishMessage(/*seq=*/0, true);
197 mClientTestChannel->assertFinishMessage(/*seq=*/1, true);
198 mClientTestChannel->assertFinishMessage(/*seq=*/2, true);
199 mClientTestChannel->assertFinishMessage(/*seq=*/3, true);
Paul Ramireze2bb1872024-08-12 20:21:13 +0000200}
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000201
202TEST_F(InputConsumerTest, BatchedEventsMultiDeviceConsumption) {
203 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}
204 .deviceId(0)
205 .action(AMOTION_EVENT_ACTION_DOWN)
206 .build());
207
Paul Ramirez87f1c012024-09-18 18:23:14 +0000208 invokeLooperCallback();
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000209 assertReceivedMotionEvent(AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
210
211 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}
212 .deviceId(0)
213 .action(AMOTION_EVENT_ACTION_MOVE)
214 .build());
215 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/2}
216 .deviceId(0)
217 .action(AMOTION_EVENT_ACTION_MOVE)
218 .build());
219 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/3}
220 .deviceId(0)
221 .action(AMOTION_EVENT_ACTION_MOVE)
222 .build());
223
224 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/4}
225 .deviceId(1)
226 .action(AMOTION_EVENT_ACTION_DOWN)
227 .build());
228
Paul Ramirez87f1c012024-09-18 18:23:14 +0000229 invokeLooperCallback();
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000230 assertReceivedMotionEvent(AllOf(WithDeviceId(1), WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
231
232 mClientTestChannel->enqueueMessage(InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/5}
233 .deviceId(0)
234 .action(AMOTION_EVENT_ACTION_UP)
235 .build());
236
Paul Ramirez87f1c012024-09-18 18:23:14 +0000237 invokeLooperCallback();
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000238 assertReceivedMotionEvent(AllOf(WithDeviceId(0), WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
239 Not(MotionEventIsResampled())));
240
241 mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
242 mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
243 mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
244 mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
245 mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
246}
Paul Ramireze2bb1872024-08-12 20:21:13 +0000247} // namespace android