blob: 1dadae98e4fc6b1f6fe0ac76de92c577bc823880 [file] [log] [blame]
Siarhei Vishniakou2b920272024-02-27 19:49:51 -08001/*
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
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -080017#include <TestEventMatchers.h>
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080018#include <android-base/logging.h>
19#include <attestation/HmacKeyManager.h>
20#include <ftl/enum.h>
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -080021#include <gmock/gmock.h>
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080022#include <gtest/gtest.h>
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080023#include <input/BlockingQueue.h>
24#include <input/InputConsumerNoResampling.h>
25#include <input/InputTransport.h>
26
27using android::base::Result;
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -080028using ::testing::Matcher;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080029
30namespace android {
31
32namespace {
33
34static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION;
35static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
36static constexpr int32_t POINTER_1_DOWN =
37 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
38static constexpr int32_t POINTER_2_DOWN =
39 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
40
41static auto constexpr TIMEOUT = 5s;
42
43struct Pointer {
44 int32_t id;
45 float x;
46 float y;
47 bool isResampled = false;
48};
49
50// A collection of arguments to be sent as publishMotionEvent(). The saved members of this struct
51// allow to check the expectations against the event acquired from the InputConsumerCallbacks. To
52// help simplify expectation checking it carries members not present in MotionEvent, like
53// |rawXScale|.
54struct PublishMotionArgs {
55 const int32_t action;
56 const nsecs_t downTime;
57 const uint32_t seq;
Paul Ramirez79655f22024-07-01 21:55:48 +000058 int32_t eventId;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080059 const int32_t deviceId = 1;
60 const uint32_t source = AINPUT_SOURCE_TOUCHSCREEN;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070061 const ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -080062 const int32_t actionButton = 0;
63 const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
64 const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
65 const int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY;
66 const MotionClassification classification = MotionClassification::AMBIGUOUS_GESTURE;
67 const float xScale = 2;
68 const float yScale = 3;
69 const float xOffset = -10;
70 const float yOffset = -20;
71 const float rawXScale = 4;
72 const float rawYScale = -5;
73 const float rawXOffset = -11;
74 const float rawYOffset = 42;
75 const float xPrecision = 0.25;
76 const float yPrecision = 0.5;
77 const float xCursorPosition = 1.3;
78 const float yCursorPosition = 50.6;
79 std::array<uint8_t, 32> hmac;
80 int32_t flags;
81 ui::Transform transform;
82 ui::Transform rawTransform;
83 const nsecs_t eventTime;
84 size_t pointerCount;
85 std::vector<PointerProperties> pointerProperties;
86 std::vector<PointerCoords> pointerCoords;
87
88 PublishMotionArgs(int32_t action, nsecs_t downTime, const std::vector<Pointer>& pointers,
89 const uint32_t seq);
90};
91
92PublishMotionArgs::PublishMotionArgs(int32_t inAction, nsecs_t inDownTime,
93 const std::vector<Pointer>& pointers, const uint32_t inSeq)
94 : action(inAction),
95 downTime(inDownTime),
96 seq(inSeq),
97 eventId(InputEvent::nextId()),
98 eventTime(systemTime(SYSTEM_TIME_MONOTONIC)) {
99 hmac = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
100 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
101
Prabir Pradhan9a53b552024-06-04 02:59:40 +0000102 flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED |
103 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION |
104 AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800105 if (action == AMOTION_EVENT_ACTION_CANCEL) {
106 flags |= AMOTION_EVENT_FLAG_CANCELED;
107 }
108 pointerCount = pointers.size();
109 for (size_t i = 0; i < pointerCount; i++) {
110 pointerProperties.push_back({});
111 pointerProperties[i].clear();
112 pointerProperties[i].id = pointers[i].id;
113 pointerProperties[i].toolType = ToolType::FINGER;
114
115 pointerCoords.push_back({});
116 pointerCoords[i].clear();
117 pointerCoords[i].isResampled = pointers[i].isResampled;
118 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, pointers[i].x);
119 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, pointers[i].y);
120 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.5 * i);
121 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 0.7 * i);
122 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 1.5 * i);
123 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 1.7 * i);
124 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 2.5 * i);
125 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 2.7 * i);
126 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
127 }
128 transform.set({xScale, 0, xOffset, 0, yScale, yOffset, 0, 0, 1});
129 rawTransform.set({rawXScale, 0, rawXOffset, 0, rawYScale, rawYOffset, 0, 0, 1});
130}
131
132// Checks expectations against |motionEvent| acquired from an InputConsumer. Floating point
133// comparisons limit precision to EPSILON.
134void verifyArgsEqualToEvent(const PublishMotionArgs& args, const MotionEvent& motionEvent) {
135 EXPECT_EQ(args.eventId, motionEvent.getId());
136 EXPECT_EQ(args.deviceId, motionEvent.getDeviceId());
137 EXPECT_EQ(args.source, motionEvent.getSource());
138 EXPECT_EQ(args.displayId, motionEvent.getDisplayId());
139 EXPECT_EQ(args.hmac, motionEvent.getHmac());
140 EXPECT_EQ(args.action, motionEvent.getAction());
141 EXPECT_EQ(args.downTime, motionEvent.getDownTime());
142 EXPECT_EQ(args.flags, motionEvent.getFlags());
143 EXPECT_EQ(args.edgeFlags, motionEvent.getEdgeFlags());
144 EXPECT_EQ(args.metaState, motionEvent.getMetaState());
145 EXPECT_EQ(args.buttonState, motionEvent.getButtonState());
146 EXPECT_EQ(args.classification, motionEvent.getClassification());
147 EXPECT_EQ(args.transform, motionEvent.getTransform());
148 EXPECT_NEAR((-args.rawXOffset / args.rawXScale) * args.xScale + args.xOffset,
149 motionEvent.getRawXOffset(), EPSILON);
150 EXPECT_NEAR((-args.rawYOffset / args.rawYScale) * args.yScale + args.yOffset,
151 motionEvent.getRawYOffset(), EPSILON);
152 EXPECT_EQ(args.xPrecision, motionEvent.getXPrecision());
153 EXPECT_EQ(args.yPrecision, motionEvent.getYPrecision());
154 EXPECT_NEAR(args.xCursorPosition, motionEvent.getRawXCursorPosition(), EPSILON);
155 EXPECT_NEAR(args.yCursorPosition, motionEvent.getRawYCursorPosition(), EPSILON);
156 EXPECT_NEAR(args.xCursorPosition * args.xScale + args.xOffset, motionEvent.getXCursorPosition(),
157 EPSILON);
158 EXPECT_NEAR(args.yCursorPosition * args.yScale + args.yOffset, motionEvent.getYCursorPosition(),
159 EPSILON);
160 EXPECT_EQ(args.rawTransform, motionEvent.getRawTransform());
161 EXPECT_EQ(args.eventTime, motionEvent.getEventTime());
162 EXPECT_EQ(args.pointerCount, motionEvent.getPointerCount());
163 EXPECT_EQ(0U, motionEvent.getHistorySize());
164
165 for (size_t i = 0; i < args.pointerCount; i++) {
166 SCOPED_TRACE(i);
167 EXPECT_EQ(args.pointerProperties[i].id, motionEvent.getPointerId(i));
168 EXPECT_EQ(args.pointerProperties[i].toolType, motionEvent.getToolType(i));
169
170 const auto& pc = args.pointerCoords[i];
171 EXPECT_EQ(pc, motionEvent.getSamplePointerCoords()[i]);
172
173 EXPECT_NEAR(pc.getX() * args.rawXScale + args.rawXOffset, motionEvent.getRawX(i), EPSILON);
174 EXPECT_NEAR(pc.getY() * args.rawYScale + args.rawYOffset, motionEvent.getRawY(i), EPSILON);
175 EXPECT_NEAR(pc.getX() * args.xScale + args.xOffset, motionEvent.getX(i), EPSILON);
176 EXPECT_NEAR(pc.getY() * args.yScale + args.yOffset, motionEvent.getY(i), EPSILON);
177 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), motionEvent.getPressure(i));
178 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_SIZE), motionEvent.getSize(i));
179 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), motionEvent.getTouchMajor(i));
180 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), motionEvent.getTouchMinor(i));
181 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), motionEvent.getToolMajor(i));
182 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), motionEvent.getToolMinor(i));
183
184 // Calculate the orientation after scaling, keeping in mind that an orientation of 0 is
185 // "up", and the positive y direction is "down".
186 const float unscaledOrientation = pc.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
187 const float x = sinf(unscaledOrientation) * args.xScale;
188 const float y = -cosf(unscaledOrientation) * args.yScale;
189 EXPECT_EQ(atan2f(x, -y), motionEvent.getOrientation(i));
190 }
191}
192
193void publishMotionEvent(InputPublisher& publisher, const PublishMotionArgs& a) {
194 status_t status =
195 publisher.publishMotionEvent(a.seq, a.eventId, a.deviceId, a.source, a.displayId,
196 a.hmac, a.action, a.actionButton, a.flags, a.edgeFlags,
197 a.metaState, a.buttonState, a.classification, a.transform,
198 a.xPrecision, a.yPrecision, a.xCursorPosition,
199 a.yCursorPosition, a.rawTransform, a.downTime, a.eventTime,
200 a.pointerCount, a.pointerProperties.data(),
201 a.pointerCoords.data());
202 ASSERT_EQ(OK, status) << "publisher publishMotionEvent should return OK";
203}
204
205Result<InputPublisher::ConsumerResponse> receiveConsumerResponse(
206 InputPublisher& publisher, std::chrono::milliseconds timeout) {
207 const std::chrono::time_point start = std::chrono::steady_clock::now();
208
209 while (true) {
210 Result<InputPublisher::ConsumerResponse> result = publisher.receiveConsumerResponse();
211 if (result.ok()) {
212 return result;
213 }
214 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
215 if (waited > timeout) {
216 return result;
217 }
218 }
219}
220
221void verifyFinishedSignal(InputPublisher& publisher, uint32_t seq, nsecs_t publishTime) {
222 Result<InputPublisher::ConsumerResponse> result = receiveConsumerResponse(publisher, TIMEOUT);
223 ASSERT_TRUE(result.ok()) << "receiveConsumerResponse returned " << result.error().message();
224 ASSERT_TRUE(std::holds_alternative<InputPublisher::Finished>(*result));
225 const InputPublisher::Finished& finish = std::get<InputPublisher::Finished>(*result);
226 ASSERT_EQ(seq, finish.seq)
227 << "receiveConsumerResponse should have returned the original sequence number";
228 ASSERT_TRUE(finish.handled)
229 << "receiveConsumerResponse should have set handled to consumer's reply";
230 ASSERT_GE(finish.consumeTime, publishTime)
231 << "finished signal's consume time should be greater than publish time";
232}
233
234} // namespace
235
236class InputConsumerMessageHandler : public MessageHandler {
237public:
238 InputConsumerMessageHandler(std::function<void(const Message&)> function)
239 : mFunction(function) {}
240
241private:
242 void handleMessage(const Message& message) override { mFunction(message); }
243
244 std::function<void(const Message&)> mFunction;
245};
246
247class InputPublisherAndConsumerNoResamplingTest : public testing::Test,
248 public InputConsumerCallbacks {
249protected:
250 std::unique_ptr<InputChannel> mClientChannel;
251 std::unique_ptr<InputPublisher> mPublisher;
252 std::unique_ptr<InputConsumerNoResampling> mConsumer;
253
254 std::thread mLooperThread;
255 sp<Looper> mLooper = sp<Looper>::make(/*allowNonCallbacks=*/false);
256
257 // LOOPER CONTROL
258 // Set to false when you want the looper to exit
259 std::atomic<bool> mExitLooper = false;
260 std::mutex mLock;
261
262 // Used by test to notify looper that the value of "mLooperMayProceed" has changed
263 std::condition_variable mNotifyLooperMayProceed;
264 bool mLooperMayProceed GUARDED_BY(mLock){true};
265 // Used by looper to notify the test that it's about to block on "mLooperMayProceed" -> true
266 std::condition_variable mNotifyLooperWaiting;
267 bool mLooperIsBlocked GUARDED_BY(mLock){false};
268
269 std::condition_variable mNotifyConsumerDestroyed;
270 bool mConsumerDestroyed GUARDED_BY(mLock){false};
271
272 void runLooper() {
273 static constexpr int LOOP_INDEFINITELY = -1;
274 Looper::setForThread(mLooper);
275 // Loop forever -- this thread is dedicated to servicing the looper callbacks.
276 while (!mExitLooper) {
277 mLooper->pollOnce(/*timeoutMillis=*/LOOP_INDEFINITELY);
278 }
279 }
280
281 void SetUp() override {
282 std::unique_ptr<InputChannel> serverChannel;
283 status_t result =
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -0800284 InputChannel::openInputChannelPair("test channel", serverChannel, mClientChannel);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800285 ASSERT_EQ(OK, result);
286
287 mPublisher = std::make_unique<InputPublisher>(std::move(serverChannel));
288 mMessageHandler = sp<InputConsumerMessageHandler>::make(
289 [this](const Message& message) { handleMessage(message); });
290 mLooperThread = std::thread([this] { runLooper(); });
291 sendMessage(LooperMessage::CREATE_CONSUMER);
292 }
293
294 void publishAndConsumeKeyEvent();
295 void publishAndConsumeMotionStream();
296 void publishAndConsumeMotionDown(nsecs_t downTime);
Paul Ramirez79655f22024-07-01 21:55:48 +0000297 void publishAndConsumeSinglePointerMultipleSamples(const size_t nSamples);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800298 void publishAndConsumeBatchedMotionMove(nsecs_t downTime);
299 void publishAndConsumeFocusEvent();
300 void publishAndConsumeCaptureEvent();
301 void publishAndConsumeDragEvent();
302 void publishAndConsumeTouchModeEvent();
303 void publishAndConsumeMotionEvent(int32_t action, nsecs_t downTime,
304 const std::vector<Pointer>& pointers);
Paul Ramirez79655f22024-07-01 21:55:48 +0000305
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800306 void TearDown() override {
307 // Destroy the consumer, flushing any of the pending ack's.
308 sendMessage(LooperMessage::DESTROY_CONSUMER);
309 {
310 std::unique_lock lock(mLock);
311 base::ScopedLockAssertion assumeLocked(mLock);
312 mNotifyConsumerDestroyed.wait(lock, [this] { return mConsumerDestroyed; });
313 }
314 // Stop the looper thread so that we can destroy the object.
315 mExitLooper = true;
316 mLooper->wake();
317 mLooperThread.join();
318 }
319
320protected:
321 // Interaction with the looper thread
Siarhei Vishniakoueb63bbf2024-11-13 15:13:29 -0800322 void blockLooper();
323 void unblockLooper();
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800324 enum class LooperMessage : int {
325 CALL_PROBABLY_HAS_INPUT,
326 CREATE_CONSUMER,
327 DESTROY_CONSUMER,
328 CALL_REPORT_TIMELINE,
329 BLOCK_LOOPER,
330 };
331 void sendMessage(LooperMessage message);
332 struct ReportTimelineArgs {
333 int32_t inputEventId;
334 nsecs_t gpuCompletedTime;
335 nsecs_t presentTime;
336 };
337 // The input to the function "InputConsumer::reportTimeline". Populated on the test thread and
338 // accessed on the looper thread.
339 BlockingQueue<ReportTimelineArgs> mReportTimelineArgs;
340 // The output of calling "InputConsumer::probablyHasInput()". Populated on the looper thread and
341 // accessed on the test thread.
342 BlockingQueue<bool> mProbablyHasInputResponses;
343
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -0800344 std::unique_ptr<MotionEvent> assertReceivedMotionEvent(const Matcher<MotionEvent>& matcher);
345
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800346private:
347 sp<MessageHandler> mMessageHandler;
348 void handleMessage(const Message& message);
349
350 static auto constexpr NO_EVENT_TIMEOUT = 10ms;
351 // The sequence number to use when publishing the next event
352 uint32_t mSeq = 1;
353
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700354 BlockingQueue<std::unique_ptr<KeyEvent>> mKeyEvents;
355 BlockingQueue<std::unique_ptr<MotionEvent>> mMotionEvents;
356 BlockingQueue<std::unique_ptr<FocusEvent>> mFocusEvents;
357 BlockingQueue<std::unique_ptr<CaptureEvent>> mCaptureEvents;
358 BlockingQueue<std::unique_ptr<DragEvent>> mDragEvents;
359 BlockingQueue<std::unique_ptr<TouchModeEvent>> mTouchModeEvents;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800360
361 // InputConsumerCallbacks interface
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700362 void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800363 mKeyEvents.push(std::move(event));
364 mConsumer->finishInputEvent(seq, true);
365 }
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700366 void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800367 mMotionEvents.push(std::move(event));
368 mConsumer->finishInputEvent(seq, true);
369 }
370 void onBatchedInputEventPending(int32_t pendingBatchSource) override {
371 if (!mConsumer->probablyHasInput()) {
372 ADD_FAILURE() << "should deterministically have input because there is a batch";
373 }
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000374 mConsumer->consumeBatchedInputEvents(/*frameTime=*/std::nullopt);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800375 };
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700376 void onFocusEvent(std::unique_ptr<FocusEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800377 mFocusEvents.push(std::move(event));
378 mConsumer->finishInputEvent(seq, true);
379 };
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700380 void onCaptureEvent(std::unique_ptr<CaptureEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800381 mCaptureEvents.push(std::move(event));
382 mConsumer->finishInputEvent(seq, true);
383 };
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700384 void onDragEvent(std::unique_ptr<DragEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800385 mDragEvents.push(std::move(event));
386 mConsumer->finishInputEvent(seq, true);
387 }
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700388 void onTouchModeEvent(std::unique_ptr<TouchModeEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800389 mTouchModeEvents.push(std::move(event));
390 mConsumer->finishInputEvent(seq, true);
391 };
392};
393
Siarhei Vishniakoueb63bbf2024-11-13 15:13:29 -0800394void InputPublisherAndConsumerNoResamplingTest::blockLooper() {
395 {
396 std::scoped_lock l(mLock);
397 mLooperMayProceed = false;
398 }
399 sendMessage(LooperMessage::BLOCK_LOOPER);
400 {
401 std::unique_lock l(mLock);
402 mNotifyLooperWaiting.wait(l, [this] { return mLooperIsBlocked; });
403 }
404}
405
406void InputPublisherAndConsumerNoResamplingTest::unblockLooper() {
407 {
408 std::scoped_lock l(mLock);
409 mLooperMayProceed = true;
410 }
411 mNotifyLooperMayProceed.notify_all();
412}
413
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800414void InputPublisherAndConsumerNoResamplingTest::sendMessage(LooperMessage message) {
415 Message msg{ftl::to_underlying(message)};
416 mLooper->sendMessage(mMessageHandler, msg);
417}
418
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -0800419std::unique_ptr<MotionEvent> InputPublisherAndConsumerNoResamplingTest::assertReceivedMotionEvent(
420 const Matcher<MotionEvent>& matcher) {
421 std::optional<std::unique_ptr<MotionEvent>> event = mMotionEvents.popWithTimeout(TIMEOUT);
422 if (!event) {
423 ADD_FAILURE() << "No event was received, but expected motion " << matcher;
424 return nullptr;
425 }
426 if (*event == nullptr) {
427 LOG(FATAL) << "Event was received, but it was null";
428 }
429 EXPECT_THAT(**event, matcher);
430 return std::move(*event);
431}
432
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800433void InputPublisherAndConsumerNoResamplingTest::handleMessage(const Message& message) {
434 switch (static_cast<LooperMessage>(message.what)) {
435 case LooperMessage::CALL_PROBABLY_HAS_INPUT: {
436 mProbablyHasInputResponses.push(mConsumer->probablyHasInput());
437 break;
438 }
439 case LooperMessage::CREATE_CONSUMER: {
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000440 mConsumer =
441 std::make_unique<InputConsumerNoResampling>(std::move(mClientChannel), mLooper,
442 *this, /*resampler=*/nullptr);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800443 break;
444 }
445 case LooperMessage::DESTROY_CONSUMER: {
446 mConsumer = nullptr;
447 {
448 std::unique_lock lock(mLock);
449 mConsumerDestroyed = true;
450 }
451 mNotifyConsumerDestroyed.notify_all();
452 break;
453 }
454 case LooperMessage::CALL_REPORT_TIMELINE: {
455 std::optional<ReportTimelineArgs> args = mReportTimelineArgs.pop();
456 if (!args.has_value()) {
457 ADD_FAILURE() << "Couldn't get the 'reportTimeline' args in time";
458 return;
459 }
460 mConsumer->reportTimeline(args->inputEventId, args->gpuCompletedTime,
461 args->presentTime);
462 break;
463 }
464 case LooperMessage::BLOCK_LOOPER: {
465 {
466 std::unique_lock lock(mLock);
467 mLooperIsBlocked = true;
468 }
469 mNotifyLooperWaiting.notify_all();
470
471 {
472 std::unique_lock lock(mLock);
473 base::ScopedLockAssertion assumeLocked(mLock);
474 mNotifyLooperMayProceed.wait(lock, [this] { return mLooperMayProceed; });
475 }
476
477 {
478 std::unique_lock lock(mLock);
479 mLooperIsBlocked = false;
480 }
481 mNotifyLooperWaiting.notify_all();
482 break;
483 }
484 }
485}
486
487void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeKeyEvent() {
488 status_t status;
489
490 const uint32_t seq = mSeq++;
491 int32_t eventId = InputEvent::nextId();
492 constexpr int32_t deviceId = 1;
493 constexpr uint32_t source = AINPUT_SOURCE_KEYBOARD;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700494 constexpr ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800495 constexpr std::array<uint8_t, 32> hmac = {31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21,
496 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,
497 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
498 constexpr int32_t action = AKEY_EVENT_ACTION_DOWN;
499 constexpr int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM;
500 constexpr int32_t keyCode = AKEYCODE_ENTER;
501 constexpr int32_t scanCode = 13;
502 constexpr int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
503 constexpr int32_t repeatCount = 1;
504 constexpr nsecs_t downTime = 3;
505 constexpr nsecs_t eventTime = 4;
506 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
507
508 status = mPublisher->publishKeyEvent(seq, eventId, deviceId, source, displayId, hmac, action,
509 flags, keyCode, scanCode, metaState, repeatCount, downTime,
510 eventTime);
511 ASSERT_EQ(OK, status) << "publisher publishKeyEvent should return OK";
512
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700513 std::optional<std::unique_ptr<KeyEvent>> optKeyEvent = mKeyEvents.popWithTimeout(TIMEOUT);
514 ASSERT_TRUE(optKeyEvent.has_value()) << "consumer should have returned non-NULL event";
515 std::unique_ptr<KeyEvent> keyEvent = std::move(*optKeyEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800516
517 sendMessage(LooperMessage::CALL_PROBABLY_HAS_INPUT);
518 std::optional<bool> probablyHasInput = mProbablyHasInputResponses.popWithTimeout(TIMEOUT);
519 ASSERT_TRUE(probablyHasInput.has_value());
520 ASSERT_FALSE(probablyHasInput.value()) << "no events should be waiting after being consumed";
521
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800522 EXPECT_EQ(eventId, keyEvent->getId());
523 EXPECT_EQ(deviceId, keyEvent->getDeviceId());
524 EXPECT_EQ(source, keyEvent->getSource());
525 EXPECT_EQ(displayId, keyEvent->getDisplayId());
526 EXPECT_EQ(hmac, keyEvent->getHmac());
527 EXPECT_EQ(action, keyEvent->getAction());
528 EXPECT_EQ(flags, keyEvent->getFlags());
529 EXPECT_EQ(keyCode, keyEvent->getKeyCode());
530 EXPECT_EQ(scanCode, keyEvent->getScanCode());
531 EXPECT_EQ(metaState, keyEvent->getMetaState());
532 EXPECT_EQ(repeatCount, keyEvent->getRepeatCount());
533 EXPECT_EQ(downTime, keyEvent->getDownTime());
534 EXPECT_EQ(eventTime, keyEvent->getEventTime());
535
536 verifyFinishedSignal(*mPublisher, seq, publishTime);
537}
538
539void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionStream() {
540 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
541
542 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_DOWN, downTime,
543 {Pointer{.id = 0, .x = 20, .y = 30}});
544
545 publishAndConsumeMotionEvent(POINTER_1_DOWN, downTime,
546 {Pointer{.id = 0, .x = 20, .y = 30},
547 Pointer{.id = 1, .x = 200, .y = 300}});
548
549 publishAndConsumeMotionEvent(POINTER_2_DOWN, downTime,
550 {Pointer{.id = 0, .x = 20, .y = 30},
551 Pointer{.id = 1, .x = 200, .y = 300},
552 Pointer{.id = 2, .x = 300, .y = 400}});
553
554 // Provide a consistent input stream - cancel the gesture that was started above
555 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_CANCEL, downTime,
556 {Pointer{.id = 0, .x = 20, .y = 30},
557 Pointer{.id = 1, .x = 200, .y = 300},
558 Pointer{.id = 2, .x = 300, .y = 400}});
559}
560
561void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionDown(nsecs_t downTime) {
562 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_DOWN, downTime,
563 {Pointer{.id = 0, .x = 20, .y = 30}});
564}
565
Paul Ramirez79655f22024-07-01 21:55:48 +0000566/*
567 * Decompose a potential multi-sampled MotionEvent into multiple MotionEvents
568 * with a single sample.
569 */
570std::vector<MotionEvent> splitBatchedMotionEvent(const MotionEvent& batchedMotionEvent) {
571 std::vector<MotionEvent> singleMotionEvents;
572 const size_t batchSize = batchedMotionEvent.getHistorySize() + 1;
573 for (size_t i = 0; i < batchSize; ++i) {
574 MotionEvent singleMotionEvent;
575 singleMotionEvent
576 .initialize(batchedMotionEvent.getId(), batchedMotionEvent.getDeviceId(),
577 batchedMotionEvent.getSource(), batchedMotionEvent.getDisplayId(),
578 batchedMotionEvent.getHmac(), batchedMotionEvent.getAction(),
579 batchedMotionEvent.getActionButton(), batchedMotionEvent.getFlags(),
580 batchedMotionEvent.getEdgeFlags(), batchedMotionEvent.getMetaState(),
581 batchedMotionEvent.getButtonState(),
582 batchedMotionEvent.getClassification(),
583 batchedMotionEvent.getTransform(), batchedMotionEvent.getXPrecision(),
584 batchedMotionEvent.getYPrecision(),
585 batchedMotionEvent.getRawXCursorPosition(),
586 batchedMotionEvent.getRawYCursorPosition(),
587 batchedMotionEvent.getRawTransform(), batchedMotionEvent.getDownTime(),
588 batchedMotionEvent.getHistoricalEventTime(/*historicalIndex=*/i),
589 batchedMotionEvent.getPointerCount(),
590 batchedMotionEvent.getPointerProperties(),
591 (batchedMotionEvent.getSamplePointerCoords() + i));
592 singleMotionEvents.push_back(singleMotionEvent);
593 }
594 return singleMotionEvents;
595}
596
597/*
598 * Simulates a single pointer touching the screen and leaving it there for a period of time.
599 * Publishes a DOWN event and consumes it right away. Then, publishes a sequence of MOVE
600 * samples for the same pointer, and waits until it has been consumed. Splits batched MotionEvents
601 * into individual samples. Checks the consumed MotionEvents against the published ones.
602 * This test is non-deterministic because it depends on the timing of arrival of events to the
603 * socket.
604 *
605 * @param nSamples The number of MOVE samples to publish before attempting consumption.
606 */
607void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeSinglePointerMultipleSamples(
608 const size_t nSamples) {
609 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
610 const Pointer pointer(0, 20, 30);
611
612 const PublishMotionArgs argsDown(AMOTION_EVENT_ACTION_DOWN, downTime, {pointer}, mSeq);
613 const nsecs_t publishTimeOfDown = systemTime(SYSTEM_TIME_MONOTONIC);
614 publishMotionEvent(*mPublisher, argsDown);
615
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -0800616 assertReceivedMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
Paul Ramirez79655f22024-07-01 21:55:48 +0000617
618 verifyFinishedSignal(*mPublisher, mSeq, publishTimeOfDown);
619
620 std::vector<nsecs_t> publishTimes;
621 std::vector<PublishMotionArgs> argsMoves;
622 std::queue<uint32_t> publishedSequenceNumbers;
623
624 // Block Looper to increase the chance of batching events
Siarhei Vishniakoueb63bbf2024-11-13 15:13:29 -0800625 blockLooper();
Paul Ramirez79655f22024-07-01 21:55:48 +0000626
627 uint32_t firstSampleId;
628 for (size_t i = 0; i < nSamples; ++i) {
629 publishedSequenceNumbers.push(++mSeq);
630 PublishMotionArgs argsMove(AMOTION_EVENT_ACTION_MOVE, downTime, {pointer}, mSeq);
631 // A batched MotionEvent only has a single event id, currently determined when the
632 // MotionEvent is initialized. Therefore, to pass the eventId comparisons inside
633 // verifyArgsEqualToEvent, we need to override the event id of the published args to match
634 // the event id of the first sample inside the MotionEvent.
635 if (i == 0) {
636 firstSampleId = argsMove.eventId;
637 }
638 argsMove.eventId = firstSampleId;
639 publishTimes.push_back(systemTime(SYSTEM_TIME_MONOTONIC));
640 argsMoves.push_back(argsMove);
641 publishMotionEvent(*mPublisher, argsMove);
642 }
643
644 std::vector<MotionEvent> singleSampledMotionEvents;
645
Siarhei Vishniakoueb63bbf2024-11-13 15:13:29 -0800646 unblockLooper();
Paul Ramirez79655f22024-07-01 21:55:48 +0000647
648 // We have no control over the socket behavior, so the consumer can receive
649 // the motion as a batched event, or as a sequence of multiple single-sample MotionEvents (or a
650 // mix of those)
651 while (singleSampledMotionEvents.size() != nSamples) {
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -0800652 const std::unique_ptr<MotionEvent> batchedMotionEvent =
653 assertReceivedMotionEvent(WithMotionAction(ACTION_MOVE));
Paul Ramirez79655f22024-07-01 21:55:48 +0000654 // The events received by these calls are never null
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -0800655 std::vector<MotionEvent> splitMotionEvents = splitBatchedMotionEvent(*batchedMotionEvent);
Paul Ramirez79655f22024-07-01 21:55:48 +0000656 singleSampledMotionEvents.insert(singleSampledMotionEvents.end(), splitMotionEvents.begin(),
657 splitMotionEvents.end());
658 }
659
660 // Consumer can choose to finish events in any order. For simplicity,
661 // we verify the events in sequence (since that is how the test is implemented).
662 for (size_t i = 0; i < nSamples; ++i) {
663 verifyArgsEqualToEvent(argsMoves[i], singleSampledMotionEvents[i]);
664 verifyFinishedSignal(*mPublisher, publishedSequenceNumbers.front(), publishTimes[i]);
665 publishedSequenceNumbers.pop();
666 }
667}
668
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800669void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeBatchedMotionMove(
670 nsecs_t downTime) {
671 uint32_t seq = mSeq++;
672 const std::vector<Pointer> pointers = {Pointer{.id = 0, .x = 20, .y = 30}};
673 PublishMotionArgs args(AMOTION_EVENT_ACTION_MOVE, downTime, pointers, seq);
674 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
675
676 // Block the looper thread, preventing it from being able to service any of the fd callbacks.
677
678 {
679 std::scoped_lock lock(mLock);
680 mLooperMayProceed = false;
681 }
682 sendMessage(LooperMessage::BLOCK_LOOPER);
683 {
684 std::unique_lock lock(mLock);
685 mNotifyLooperWaiting.wait(lock, [this] { return mLooperIsBlocked; });
686 }
687
688 publishMotionEvent(*mPublisher, args);
689
690 // Ensure no event arrives because the UI thread is blocked
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700691 std::optional<std::unique_ptr<MotionEvent>> noEvent =
692 mMotionEvents.popWithTimeout(NO_EVENT_TIMEOUT);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800693 ASSERT_FALSE(noEvent.has_value()) << "Got unexpected event: " << *noEvent;
694
695 Result<InputPublisher::ConsumerResponse> result = mPublisher->receiveConsumerResponse();
696 ASSERT_FALSE(result.ok());
697 ASSERT_EQ(WOULD_BLOCK, result.error().code());
698
699 // We shouldn't be calling mConsumer on the UI thread, but in this situation, the looper
700 // thread is locked, so this should be safe to do.
701 ASSERT_TRUE(mConsumer->probablyHasInput())
702 << "should deterministically have input because there is a batch";
703
704 // Now, unblock the looper thread, so that the event can arrive.
705 {
706 std::scoped_lock lock(mLock);
707 mLooperMayProceed = true;
708 }
709 mNotifyLooperMayProceed.notify_all();
710
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -0800711 assertReceivedMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800712
713 verifyFinishedSignal(*mPublisher, seq, publishTime);
714}
715
716void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionEvent(
717 int32_t action, nsecs_t downTime, const std::vector<Pointer>& pointers) {
718 uint32_t seq = mSeq++;
719 PublishMotionArgs args(action, downTime, pointers, seq);
720 nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
721 publishMotionEvent(*mPublisher, args);
722
Siarhei Vishniakou8047b3c2024-11-15 16:01:41 -0800723 std::unique_ptr<MotionEvent> event = assertReceivedMotionEvent(WithMotionAction(action));
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800724
725 verifyArgsEqualToEvent(args, *event);
726
727 verifyFinishedSignal(*mPublisher, seq, publishTime);
728}
729
730void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeFocusEvent() {
731 status_t status;
732
733 constexpr uint32_t seq = 15;
734 int32_t eventId = InputEvent::nextId();
735 constexpr bool hasFocus = true;
736 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
737
738 status = mPublisher->publishFocusEvent(seq, eventId, hasFocus);
739 ASSERT_EQ(OK, status) << "publisher publishFocusEvent should return OK";
740
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700741 std::optional<std::unique_ptr<FocusEvent>> optFocusEvent = mFocusEvents.popWithTimeout(TIMEOUT);
742 ASSERT_TRUE(optFocusEvent.has_value()) << "consumer should have returned non-NULL event";
743 std::unique_ptr<FocusEvent> focusEvent = std::move(*optFocusEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800744 EXPECT_EQ(eventId, focusEvent->getId());
745 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
746
747 verifyFinishedSignal(*mPublisher, seq, publishTime);
748}
749
750void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeCaptureEvent() {
751 status_t status;
752
753 constexpr uint32_t seq = 42;
754 int32_t eventId = InputEvent::nextId();
755 constexpr bool captureEnabled = true;
756 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
757
758 status = mPublisher->publishCaptureEvent(seq, eventId, captureEnabled);
759 ASSERT_EQ(OK, status) << "publisher publishCaptureEvent should return OK";
760
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700761 std::optional<std::unique_ptr<CaptureEvent>> optEvent = mCaptureEvents.popWithTimeout(TIMEOUT);
762 ASSERT_TRUE(optEvent.has_value()) << "consumer should have returned non-NULL event";
763 std::unique_ptr<CaptureEvent> event = std::move(*optEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800764
765 const CaptureEvent& captureEvent = *event;
766 EXPECT_EQ(eventId, captureEvent.getId());
767 EXPECT_EQ(captureEnabled, captureEvent.getPointerCaptureEnabled());
768
769 verifyFinishedSignal(*mPublisher, seq, publishTime);
770}
771
772void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeDragEvent() {
773 status_t status;
774
775 constexpr uint32_t seq = 15;
776 int32_t eventId = InputEvent::nextId();
777 constexpr bool isExiting = false;
778 constexpr float x = 10;
779 constexpr float y = 15;
780 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
781
782 status = mPublisher->publishDragEvent(seq, eventId, x, y, isExiting);
783 ASSERT_EQ(OK, status) << "publisher publishDragEvent should return OK";
784
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700785 std::optional<std::unique_ptr<DragEvent>> optEvent = mDragEvents.popWithTimeout(TIMEOUT);
786 ASSERT_TRUE(optEvent.has_value()) << "consumer should have returned non-NULL event";
787 std::unique_ptr<DragEvent> event = std::move(*optEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800788
789 const DragEvent& dragEvent = *event;
790 EXPECT_EQ(eventId, dragEvent.getId());
791 EXPECT_EQ(isExiting, dragEvent.isExiting());
792 EXPECT_EQ(x, dragEvent.getX());
793 EXPECT_EQ(y, dragEvent.getY());
794
795 verifyFinishedSignal(*mPublisher, seq, publishTime);
796}
797
798void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeTouchModeEvent() {
799 status_t status;
800
801 constexpr uint32_t seq = 15;
802 int32_t eventId = InputEvent::nextId();
803 constexpr bool touchModeEnabled = true;
804 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
805
806 status = mPublisher->publishTouchModeEvent(seq, eventId, touchModeEnabled);
807 ASSERT_EQ(OK, status) << "publisher publishTouchModeEvent should return OK";
808
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700809 std::optional<std::unique_ptr<TouchModeEvent>> optEvent =
810 mTouchModeEvents.popWithTimeout(TIMEOUT);
811 ASSERT_TRUE(optEvent.has_value());
812 std::unique_ptr<TouchModeEvent> event = std::move(*optEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800813
814 const TouchModeEvent& touchModeEvent = *event;
815 EXPECT_EQ(eventId, touchModeEvent.getId());
816 EXPECT_EQ(touchModeEnabled, touchModeEvent.isInTouchMode());
817
818 verifyFinishedSignal(*mPublisher, seq, publishTime);
819}
820
Siarhei Vishniakoueb63bbf2024-11-13 15:13:29 -0800821/**
822 * If the publisher has died, consumer should not crash when trying to send an outgoing message.
823 */
824TEST_F(InputPublisherAndConsumerNoResamplingTest, ConsumerWritesAfterPublisherDies) {
825 mPublisher.reset(); // The publisher has died
826 mReportTimelineArgs.emplace(/*inputEventId=*/10, /*gpuCompletedTime=*/20, /*presentTime=*/30);
827 sendMessage(LooperMessage::CALL_REPORT_TIMELINE);
828}
829
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800830TEST_F(InputPublisherAndConsumerNoResamplingTest, SendTimeline) {
831 const int32_t inputEventId = 20;
832 const nsecs_t gpuCompletedTime = 30;
833 const nsecs_t presentTime = 40;
834
835 mReportTimelineArgs.emplace(inputEventId, gpuCompletedTime, presentTime);
836 sendMessage(LooperMessage::CALL_REPORT_TIMELINE);
837
838 Result<InputPublisher::ConsumerResponse> result = receiveConsumerResponse(*mPublisher, TIMEOUT);
839 ASSERT_TRUE(result.ok()) << "receiveConsumerResponse should return OK";
840 ASSERT_TRUE(std::holds_alternative<InputPublisher::Timeline>(*result));
841 const InputPublisher::Timeline& timeline = std::get<InputPublisher::Timeline>(*result);
842 ASSERT_EQ(inputEventId, timeline.inputEventId);
843 ASSERT_EQ(gpuCompletedTime, timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME]);
844 ASSERT_EQ(presentTime, timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
845}
846
847TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishKeyEvent_EndToEnd) {
848 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
849}
850
851TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMotionEvent_EndToEnd) {
852 ASSERT_NO_FATAL_FAILURE(publishAndConsumeMotionStream());
853}
854
855TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMotionMoveEvent_EndToEnd) {
856 // Publish a DOWN event before MOVE to pass the InputVerifier checks.
857 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
858 ASSERT_NO_FATAL_FAILURE(publishAndConsumeMotionDown(downTime));
859
860 // Publish the MOVE event and check expectations.
861 ASSERT_NO_FATAL_FAILURE(publishAndConsumeBatchedMotionMove(downTime));
862}
863
864TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishFocusEvent_EndToEnd) {
865 ASSERT_NO_FATAL_FAILURE(publishAndConsumeFocusEvent());
866}
867
868TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishCaptureEvent_EndToEnd) {
869 ASSERT_NO_FATAL_FAILURE(publishAndConsumeCaptureEvent());
870}
871
872TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishDragEvent_EndToEnd) {
873 ASSERT_NO_FATAL_FAILURE(publishAndConsumeDragEvent());
874}
875
876TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishTouchModeEvent_EndToEnd) {
877 ASSERT_NO_FATAL_FAILURE(publishAndConsumeTouchModeEvent());
878}
879
880TEST_F(InputPublisherAndConsumerNoResamplingTest,
881 PublishMotionEvent_WhenSequenceNumberIsZero_ReturnsError) {
882 status_t status;
883 const size_t pointerCount = 1;
884 PointerProperties pointerProperties[pointerCount];
885 PointerCoords pointerCoords[pointerCount];
886 for (size_t i = 0; i < pointerCount; i++) {
887 pointerProperties[i].clear();
888 pointerCoords[i].clear();
889 }
890
891 ui::Transform identityTransform;
892 status =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700893 mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0,
894 ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
895 0, 0, MotionClassification::NONE, identityTransform, 0,
896 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800897 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
898 0, 0, pointerCount, pointerProperties, pointerCoords);
899 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
900}
901
902TEST_F(InputPublisherAndConsumerNoResamplingTest,
903 PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
904 status_t status;
905 const size_t pointerCount = 0;
906 PointerProperties pointerProperties[pointerCount];
907 PointerCoords pointerCoords[pointerCount];
908
909 ui::Transform identityTransform;
910 status =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700911 mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0,
912 ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
913 0, 0, MotionClassification::NONE, identityTransform, 0,
914 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800915 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
916 0, 0, pointerCount, pointerProperties, pointerCoords);
917 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
918}
919
920TEST_F(InputPublisherAndConsumerNoResamplingTest,
921 PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
922 status_t status;
923 const size_t pointerCount = MAX_POINTERS + 1;
924 PointerProperties pointerProperties[pointerCount];
925 PointerCoords pointerCoords[pointerCount];
926 for (size_t i = 0; i < pointerCount; i++) {
927 pointerProperties[i].clear();
928 pointerCoords[i].clear();
929 }
930
931 ui::Transform identityTransform;
932 status =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700933 mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0,
934 ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
935 0, 0, MotionClassification::NONE, identityTransform, 0,
936 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800937 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
938 0, 0, pointerCount, pointerProperties, pointerCoords);
939 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
940}
941
942TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMultipleEvents_EndToEnd) {
943 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
944
945 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_DOWN, downTime,
946 {Pointer{.id = 0, .x = 20, .y = 30}});
947 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
948 publishAndConsumeMotionEvent(POINTER_1_DOWN, downTime,
949 {Pointer{.id = 0, .x = 20, .y = 30},
950 Pointer{.id = 1, .x = 200, .y = 300}});
951 ASSERT_NO_FATAL_FAILURE(publishAndConsumeFocusEvent());
952 publishAndConsumeMotionEvent(POINTER_2_DOWN, downTime,
953 {Pointer{.id = 0, .x = 20, .y = 30},
954 Pointer{.id = 1, .x = 200, .y = 300},
955 Pointer{.id = 2, .x = 200, .y = 300}});
956 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
957 ASSERT_NO_FATAL_FAILURE(publishAndConsumeCaptureEvent());
958 ASSERT_NO_FATAL_FAILURE(publishAndConsumeDragEvent());
959 // Provide a consistent input stream - cancel the gesture that was started above
960 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_CANCEL, downTime,
961 {Pointer{.id = 0, .x = 20, .y = 30},
962 Pointer{.id = 1, .x = 200, .y = 300},
963 Pointer{.id = 2, .x = 200, .y = 300}});
964 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
965 ASSERT_NO_FATAL_FAILURE(publishAndConsumeTouchModeEvent());
966}
967
Paul Ramirez79655f22024-07-01 21:55:48 +0000968TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishAndConsumeSinglePointer) {
969 publishAndConsumeSinglePointerMultipleSamples(3);
970}
971
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800972} // namespace android