blob: e24ae49c096564551efa727fc60d0cfb3416434b [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
17#include <android-base/logging.h>
18#include <attestation/HmacKeyManager.h>
19#include <ftl/enum.h>
20#include <gtest/gtest.h>
21#include <gui/constants.h>
22#include <input/BlockingQueue.h>
23#include <input/InputConsumerNoResampling.h>
24#include <input/InputTransport.h>
25
26using android::base::Result;
27
28namespace android {
29
30namespace {
31
32static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION;
33static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
34static constexpr int32_t POINTER_1_DOWN =
35 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
36static constexpr int32_t POINTER_2_DOWN =
37 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
38
39static auto constexpr TIMEOUT = 5s;
40
41struct Pointer {
42 int32_t id;
43 float x;
44 float y;
45 bool isResampled = false;
46};
47
48// A collection of arguments to be sent as publishMotionEvent(). The saved members of this struct
49// allow to check the expectations against the event acquired from the InputConsumerCallbacks. To
50// help simplify expectation checking it carries members not present in MotionEvent, like
51// |rawXScale|.
52struct PublishMotionArgs {
53 const int32_t action;
54 const nsecs_t downTime;
55 const uint32_t seq;
56 const int32_t eventId;
57 const int32_t deviceId = 1;
58 const uint32_t source = AINPUT_SOURCE_TOUCHSCREEN;
59 const int32_t displayId = ADISPLAY_ID_DEFAULT;
60 const int32_t actionButton = 0;
61 const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
62 const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
63 const int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY;
64 const MotionClassification classification = MotionClassification::AMBIGUOUS_GESTURE;
65 const float xScale = 2;
66 const float yScale = 3;
67 const float xOffset = -10;
68 const float yOffset = -20;
69 const float rawXScale = 4;
70 const float rawYScale = -5;
71 const float rawXOffset = -11;
72 const float rawYOffset = 42;
73 const float xPrecision = 0.25;
74 const float yPrecision = 0.5;
75 const float xCursorPosition = 1.3;
76 const float yCursorPosition = 50.6;
77 std::array<uint8_t, 32> hmac;
78 int32_t flags;
79 ui::Transform transform;
80 ui::Transform rawTransform;
81 const nsecs_t eventTime;
82 size_t pointerCount;
83 std::vector<PointerProperties> pointerProperties;
84 std::vector<PointerCoords> pointerCoords;
85
86 PublishMotionArgs(int32_t action, nsecs_t downTime, const std::vector<Pointer>& pointers,
87 const uint32_t seq);
88};
89
90PublishMotionArgs::PublishMotionArgs(int32_t inAction, nsecs_t inDownTime,
91 const std::vector<Pointer>& pointers, const uint32_t inSeq)
92 : action(inAction),
93 downTime(inDownTime),
94 seq(inSeq),
95 eventId(InputEvent::nextId()),
96 eventTime(systemTime(SYSTEM_TIME_MONOTONIC)) {
97 hmac = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
98 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
99
100 flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
101 if (action == AMOTION_EVENT_ACTION_CANCEL) {
102 flags |= AMOTION_EVENT_FLAG_CANCELED;
103 }
104 pointerCount = pointers.size();
105 for (size_t i = 0; i < pointerCount; i++) {
106 pointerProperties.push_back({});
107 pointerProperties[i].clear();
108 pointerProperties[i].id = pointers[i].id;
109 pointerProperties[i].toolType = ToolType::FINGER;
110
111 pointerCoords.push_back({});
112 pointerCoords[i].clear();
113 pointerCoords[i].isResampled = pointers[i].isResampled;
114 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, pointers[i].x);
115 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, pointers[i].y);
116 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.5 * i);
117 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 0.7 * i);
118 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 1.5 * i);
119 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 1.7 * i);
120 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 2.5 * i);
121 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 2.7 * i);
122 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
123 }
124 transform.set({xScale, 0, xOffset, 0, yScale, yOffset, 0, 0, 1});
125 rawTransform.set({rawXScale, 0, rawXOffset, 0, rawYScale, rawYOffset, 0, 0, 1});
126}
127
128// Checks expectations against |motionEvent| acquired from an InputConsumer. Floating point
129// comparisons limit precision to EPSILON.
130void verifyArgsEqualToEvent(const PublishMotionArgs& args, const MotionEvent& motionEvent) {
131 EXPECT_EQ(args.eventId, motionEvent.getId());
132 EXPECT_EQ(args.deviceId, motionEvent.getDeviceId());
133 EXPECT_EQ(args.source, motionEvent.getSource());
134 EXPECT_EQ(args.displayId, motionEvent.getDisplayId());
135 EXPECT_EQ(args.hmac, motionEvent.getHmac());
136 EXPECT_EQ(args.action, motionEvent.getAction());
137 EXPECT_EQ(args.downTime, motionEvent.getDownTime());
138 EXPECT_EQ(args.flags, motionEvent.getFlags());
139 EXPECT_EQ(args.edgeFlags, motionEvent.getEdgeFlags());
140 EXPECT_EQ(args.metaState, motionEvent.getMetaState());
141 EXPECT_EQ(args.buttonState, motionEvent.getButtonState());
142 EXPECT_EQ(args.classification, motionEvent.getClassification());
143 EXPECT_EQ(args.transform, motionEvent.getTransform());
144 EXPECT_NEAR((-args.rawXOffset / args.rawXScale) * args.xScale + args.xOffset,
145 motionEvent.getRawXOffset(), EPSILON);
146 EXPECT_NEAR((-args.rawYOffset / args.rawYScale) * args.yScale + args.yOffset,
147 motionEvent.getRawYOffset(), EPSILON);
148 EXPECT_EQ(args.xPrecision, motionEvent.getXPrecision());
149 EXPECT_EQ(args.yPrecision, motionEvent.getYPrecision());
150 EXPECT_NEAR(args.xCursorPosition, motionEvent.getRawXCursorPosition(), EPSILON);
151 EXPECT_NEAR(args.yCursorPosition, motionEvent.getRawYCursorPosition(), EPSILON);
152 EXPECT_NEAR(args.xCursorPosition * args.xScale + args.xOffset, motionEvent.getXCursorPosition(),
153 EPSILON);
154 EXPECT_NEAR(args.yCursorPosition * args.yScale + args.yOffset, motionEvent.getYCursorPosition(),
155 EPSILON);
156 EXPECT_EQ(args.rawTransform, motionEvent.getRawTransform());
157 EXPECT_EQ(args.eventTime, motionEvent.getEventTime());
158 EXPECT_EQ(args.pointerCount, motionEvent.getPointerCount());
159 EXPECT_EQ(0U, motionEvent.getHistorySize());
160
161 for (size_t i = 0; i < args.pointerCount; i++) {
162 SCOPED_TRACE(i);
163 EXPECT_EQ(args.pointerProperties[i].id, motionEvent.getPointerId(i));
164 EXPECT_EQ(args.pointerProperties[i].toolType, motionEvent.getToolType(i));
165
166 const auto& pc = args.pointerCoords[i];
167 EXPECT_EQ(pc, motionEvent.getSamplePointerCoords()[i]);
168
169 EXPECT_NEAR(pc.getX() * args.rawXScale + args.rawXOffset, motionEvent.getRawX(i), EPSILON);
170 EXPECT_NEAR(pc.getY() * args.rawYScale + args.rawYOffset, motionEvent.getRawY(i), EPSILON);
171 EXPECT_NEAR(pc.getX() * args.xScale + args.xOffset, motionEvent.getX(i), EPSILON);
172 EXPECT_NEAR(pc.getY() * args.yScale + args.yOffset, motionEvent.getY(i), EPSILON);
173 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), motionEvent.getPressure(i));
174 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_SIZE), motionEvent.getSize(i));
175 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), motionEvent.getTouchMajor(i));
176 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), motionEvent.getTouchMinor(i));
177 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), motionEvent.getToolMajor(i));
178 EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), motionEvent.getToolMinor(i));
179
180 // Calculate the orientation after scaling, keeping in mind that an orientation of 0 is
181 // "up", and the positive y direction is "down".
182 const float unscaledOrientation = pc.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
183 const float x = sinf(unscaledOrientation) * args.xScale;
184 const float y = -cosf(unscaledOrientation) * args.yScale;
185 EXPECT_EQ(atan2f(x, -y), motionEvent.getOrientation(i));
186 }
187}
188
189void publishMotionEvent(InputPublisher& publisher, const PublishMotionArgs& a) {
190 status_t status =
191 publisher.publishMotionEvent(a.seq, a.eventId, a.deviceId, a.source, a.displayId,
192 a.hmac, a.action, a.actionButton, a.flags, a.edgeFlags,
193 a.metaState, a.buttonState, a.classification, a.transform,
194 a.xPrecision, a.yPrecision, a.xCursorPosition,
195 a.yCursorPosition, a.rawTransform, a.downTime, a.eventTime,
196 a.pointerCount, a.pointerProperties.data(),
197 a.pointerCoords.data());
198 ASSERT_EQ(OK, status) << "publisher publishMotionEvent should return OK";
199}
200
201Result<InputPublisher::ConsumerResponse> receiveConsumerResponse(
202 InputPublisher& publisher, std::chrono::milliseconds timeout) {
203 const std::chrono::time_point start = std::chrono::steady_clock::now();
204
205 while (true) {
206 Result<InputPublisher::ConsumerResponse> result = publisher.receiveConsumerResponse();
207 if (result.ok()) {
208 return result;
209 }
210 const std::chrono::duration waited = std::chrono::steady_clock::now() - start;
211 if (waited > timeout) {
212 return result;
213 }
214 }
215}
216
217void verifyFinishedSignal(InputPublisher& publisher, uint32_t seq, nsecs_t publishTime) {
218 Result<InputPublisher::ConsumerResponse> result = receiveConsumerResponse(publisher, TIMEOUT);
219 ASSERT_TRUE(result.ok()) << "receiveConsumerResponse returned " << result.error().message();
220 ASSERT_TRUE(std::holds_alternative<InputPublisher::Finished>(*result));
221 const InputPublisher::Finished& finish = std::get<InputPublisher::Finished>(*result);
222 ASSERT_EQ(seq, finish.seq)
223 << "receiveConsumerResponse should have returned the original sequence number";
224 ASSERT_TRUE(finish.handled)
225 << "receiveConsumerResponse should have set handled to consumer's reply";
226 ASSERT_GE(finish.consumeTime, publishTime)
227 << "finished signal's consume time should be greater than publish time";
228}
229
230} // namespace
231
232class InputConsumerMessageHandler : public MessageHandler {
233public:
234 InputConsumerMessageHandler(std::function<void(const Message&)> function)
235 : mFunction(function) {}
236
237private:
238 void handleMessage(const Message& message) override { mFunction(message); }
239
240 std::function<void(const Message&)> mFunction;
241};
242
243class InputPublisherAndConsumerNoResamplingTest : public testing::Test,
244 public InputConsumerCallbacks {
245protected:
246 std::unique_ptr<InputChannel> mClientChannel;
247 std::unique_ptr<InputPublisher> mPublisher;
248 std::unique_ptr<InputConsumerNoResampling> mConsumer;
249
250 std::thread mLooperThread;
251 sp<Looper> mLooper = sp<Looper>::make(/*allowNonCallbacks=*/false);
252
253 // LOOPER CONTROL
254 // Set to false when you want the looper to exit
255 std::atomic<bool> mExitLooper = false;
256 std::mutex mLock;
257
258 // Used by test to notify looper that the value of "mLooperMayProceed" has changed
259 std::condition_variable mNotifyLooperMayProceed;
260 bool mLooperMayProceed GUARDED_BY(mLock){true};
261 // Used by looper to notify the test that it's about to block on "mLooperMayProceed" -> true
262 std::condition_variable mNotifyLooperWaiting;
263 bool mLooperIsBlocked GUARDED_BY(mLock){false};
264
265 std::condition_variable mNotifyConsumerDestroyed;
266 bool mConsumerDestroyed GUARDED_BY(mLock){false};
267
268 void runLooper() {
269 static constexpr int LOOP_INDEFINITELY = -1;
270 Looper::setForThread(mLooper);
271 // Loop forever -- this thread is dedicated to servicing the looper callbacks.
272 while (!mExitLooper) {
273 mLooper->pollOnce(/*timeoutMillis=*/LOOP_INDEFINITELY);
274 }
275 }
276
277 void SetUp() override {
278 std::unique_ptr<InputChannel> serverChannel;
279 status_t result =
280 InputChannel::openInputChannelPair("channel name", serverChannel, mClientChannel);
281 ASSERT_EQ(OK, result);
282
283 mPublisher = std::make_unique<InputPublisher>(std::move(serverChannel));
284 mMessageHandler = sp<InputConsumerMessageHandler>::make(
285 [this](const Message& message) { handleMessage(message); });
286 mLooperThread = std::thread([this] { runLooper(); });
287 sendMessage(LooperMessage::CREATE_CONSUMER);
288 }
289
290 void publishAndConsumeKeyEvent();
291 void publishAndConsumeMotionStream();
292 void publishAndConsumeMotionDown(nsecs_t downTime);
293 void publishAndConsumeBatchedMotionMove(nsecs_t downTime);
294 void publishAndConsumeFocusEvent();
295 void publishAndConsumeCaptureEvent();
296 void publishAndConsumeDragEvent();
297 void publishAndConsumeTouchModeEvent();
298 void publishAndConsumeMotionEvent(int32_t action, nsecs_t downTime,
299 const std::vector<Pointer>& pointers);
300 void TearDown() override {
301 // Destroy the consumer, flushing any of the pending ack's.
302 sendMessage(LooperMessage::DESTROY_CONSUMER);
303 {
304 std::unique_lock lock(mLock);
305 base::ScopedLockAssertion assumeLocked(mLock);
306 mNotifyConsumerDestroyed.wait(lock, [this] { return mConsumerDestroyed; });
307 }
308 // Stop the looper thread so that we can destroy the object.
309 mExitLooper = true;
310 mLooper->wake();
311 mLooperThread.join();
312 }
313
314protected:
315 // Interaction with the looper thread
316 enum class LooperMessage : int {
317 CALL_PROBABLY_HAS_INPUT,
318 CREATE_CONSUMER,
319 DESTROY_CONSUMER,
320 CALL_REPORT_TIMELINE,
321 BLOCK_LOOPER,
322 };
323 void sendMessage(LooperMessage message);
324 struct ReportTimelineArgs {
325 int32_t inputEventId;
326 nsecs_t gpuCompletedTime;
327 nsecs_t presentTime;
328 };
329 // The input to the function "InputConsumer::reportTimeline". Populated on the test thread and
330 // accessed on the looper thread.
331 BlockingQueue<ReportTimelineArgs> mReportTimelineArgs;
332 // The output of calling "InputConsumer::probablyHasInput()". Populated on the looper thread and
333 // accessed on the test thread.
334 BlockingQueue<bool> mProbablyHasInputResponses;
335
336private:
337 sp<MessageHandler> mMessageHandler;
338 void handleMessage(const Message& message);
339
340 static auto constexpr NO_EVENT_TIMEOUT = 10ms;
341 // The sequence number to use when publishing the next event
342 uint32_t mSeq = 1;
343
344 BlockingQueue<KeyEvent> mKeyEvents;
345 BlockingQueue<MotionEvent> mMotionEvents;
346 BlockingQueue<FocusEvent> mFocusEvents;
347 BlockingQueue<CaptureEvent> mCaptureEvents;
348 BlockingQueue<DragEvent> mDragEvents;
349 BlockingQueue<TouchModeEvent> mTouchModeEvents;
350
351 // InputConsumerCallbacks interface
352 void onKeyEvent(KeyEvent&& event, uint32_t seq) override {
353 mKeyEvents.push(std::move(event));
354 mConsumer->finishInputEvent(seq, true);
355 }
356 void onMotionEvent(MotionEvent&& event, uint32_t seq) override {
357 mMotionEvents.push(std::move(event));
358 mConsumer->finishInputEvent(seq, true);
359 }
360 void onBatchedInputEventPending(int32_t pendingBatchSource) override {
361 if (!mConsumer->probablyHasInput()) {
362 ADD_FAILURE() << "should deterministically have input because there is a batch";
363 }
364 mConsumer->consumeBatchedInputEvents(std::nullopt);
365 };
366 void onFocusEvent(FocusEvent&& event, uint32_t seq) override {
367 mFocusEvents.push(std::move(event));
368 mConsumer->finishInputEvent(seq, true);
369 };
370 void onCaptureEvent(CaptureEvent&& event, uint32_t seq) override {
371 mCaptureEvents.push(std::move(event));
372 mConsumer->finishInputEvent(seq, true);
373 };
374 void onDragEvent(DragEvent&& event, uint32_t seq) override {
375 mDragEvents.push(std::move(event));
376 mConsumer->finishInputEvent(seq, true);
377 }
378 void onTouchModeEvent(TouchModeEvent&& event, uint32_t seq) override {
379 mTouchModeEvents.push(std::move(event));
380 mConsumer->finishInputEvent(seq, true);
381 };
382};
383
384void InputPublisherAndConsumerNoResamplingTest::sendMessage(LooperMessage message) {
385 Message msg{ftl::to_underlying(message)};
386 mLooper->sendMessage(mMessageHandler, msg);
387}
388
389void InputPublisherAndConsumerNoResamplingTest::handleMessage(const Message& message) {
390 switch (static_cast<LooperMessage>(message.what)) {
391 case LooperMessage::CALL_PROBABLY_HAS_INPUT: {
392 mProbablyHasInputResponses.push(mConsumer->probablyHasInput());
393 break;
394 }
395 case LooperMessage::CREATE_CONSUMER: {
396 mConsumer = std::make_unique<InputConsumerNoResampling>(std::move(mClientChannel),
397 mLooper, *this);
398 break;
399 }
400 case LooperMessage::DESTROY_CONSUMER: {
401 mConsumer = nullptr;
402 {
403 std::unique_lock lock(mLock);
404 mConsumerDestroyed = true;
405 }
406 mNotifyConsumerDestroyed.notify_all();
407 break;
408 }
409 case LooperMessage::CALL_REPORT_TIMELINE: {
410 std::optional<ReportTimelineArgs> args = mReportTimelineArgs.pop();
411 if (!args.has_value()) {
412 ADD_FAILURE() << "Couldn't get the 'reportTimeline' args in time";
413 return;
414 }
415 mConsumer->reportTimeline(args->inputEventId, args->gpuCompletedTime,
416 args->presentTime);
417 break;
418 }
419 case LooperMessage::BLOCK_LOOPER: {
420 {
421 std::unique_lock lock(mLock);
422 mLooperIsBlocked = true;
423 }
424 mNotifyLooperWaiting.notify_all();
425
426 {
427 std::unique_lock lock(mLock);
428 base::ScopedLockAssertion assumeLocked(mLock);
429 mNotifyLooperMayProceed.wait(lock, [this] { return mLooperMayProceed; });
430 }
431
432 {
433 std::unique_lock lock(mLock);
434 mLooperIsBlocked = false;
435 }
436 mNotifyLooperWaiting.notify_all();
437 break;
438 }
439 }
440}
441
442void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeKeyEvent() {
443 status_t status;
444
445 const uint32_t seq = mSeq++;
446 int32_t eventId = InputEvent::nextId();
447 constexpr int32_t deviceId = 1;
448 constexpr uint32_t source = AINPUT_SOURCE_KEYBOARD;
449 constexpr int32_t displayId = ADISPLAY_ID_DEFAULT;
450 constexpr std::array<uint8_t, 32> hmac = {31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21,
451 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,
452 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
453 constexpr int32_t action = AKEY_EVENT_ACTION_DOWN;
454 constexpr int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM;
455 constexpr int32_t keyCode = AKEYCODE_ENTER;
456 constexpr int32_t scanCode = 13;
457 constexpr int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
458 constexpr int32_t repeatCount = 1;
459 constexpr nsecs_t downTime = 3;
460 constexpr nsecs_t eventTime = 4;
461 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
462
463 status = mPublisher->publishKeyEvent(seq, eventId, deviceId, source, displayId, hmac, action,
464 flags, keyCode, scanCode, metaState, repeatCount, downTime,
465 eventTime);
466 ASSERT_EQ(OK, status) << "publisher publishKeyEvent should return OK";
467
468 std::optional<KeyEvent> keyEvent = mKeyEvents.popWithTimeout(TIMEOUT);
469
470 sendMessage(LooperMessage::CALL_PROBABLY_HAS_INPUT);
471 std::optional<bool> probablyHasInput = mProbablyHasInputResponses.popWithTimeout(TIMEOUT);
472 ASSERT_TRUE(probablyHasInput.has_value());
473 ASSERT_FALSE(probablyHasInput.value()) << "no events should be waiting after being consumed";
474
475 ASSERT_TRUE(keyEvent.has_value()) << "consumer should have returned non-NULL event";
476
477 EXPECT_EQ(eventId, keyEvent->getId());
478 EXPECT_EQ(deviceId, keyEvent->getDeviceId());
479 EXPECT_EQ(source, keyEvent->getSource());
480 EXPECT_EQ(displayId, keyEvent->getDisplayId());
481 EXPECT_EQ(hmac, keyEvent->getHmac());
482 EXPECT_EQ(action, keyEvent->getAction());
483 EXPECT_EQ(flags, keyEvent->getFlags());
484 EXPECT_EQ(keyCode, keyEvent->getKeyCode());
485 EXPECT_EQ(scanCode, keyEvent->getScanCode());
486 EXPECT_EQ(metaState, keyEvent->getMetaState());
487 EXPECT_EQ(repeatCount, keyEvent->getRepeatCount());
488 EXPECT_EQ(downTime, keyEvent->getDownTime());
489 EXPECT_EQ(eventTime, keyEvent->getEventTime());
490
491 verifyFinishedSignal(*mPublisher, seq, publishTime);
492}
493
494void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionStream() {
495 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
496
497 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_DOWN, downTime,
498 {Pointer{.id = 0, .x = 20, .y = 30}});
499
500 publishAndConsumeMotionEvent(POINTER_1_DOWN, downTime,
501 {Pointer{.id = 0, .x = 20, .y = 30},
502 Pointer{.id = 1, .x = 200, .y = 300}});
503
504 publishAndConsumeMotionEvent(POINTER_2_DOWN, downTime,
505 {Pointer{.id = 0, .x = 20, .y = 30},
506 Pointer{.id = 1, .x = 200, .y = 300},
507 Pointer{.id = 2, .x = 300, .y = 400}});
508
509 // Provide a consistent input stream - cancel the gesture that was started above
510 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_CANCEL, downTime,
511 {Pointer{.id = 0, .x = 20, .y = 30},
512 Pointer{.id = 1, .x = 200, .y = 300},
513 Pointer{.id = 2, .x = 300, .y = 400}});
514}
515
516void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionDown(nsecs_t downTime) {
517 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_DOWN, downTime,
518 {Pointer{.id = 0, .x = 20, .y = 30}});
519}
520
521void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeBatchedMotionMove(
522 nsecs_t downTime) {
523 uint32_t seq = mSeq++;
524 const std::vector<Pointer> pointers = {Pointer{.id = 0, .x = 20, .y = 30}};
525 PublishMotionArgs args(AMOTION_EVENT_ACTION_MOVE, downTime, pointers, seq);
526 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
527
528 // Block the looper thread, preventing it from being able to service any of the fd callbacks.
529
530 {
531 std::scoped_lock lock(mLock);
532 mLooperMayProceed = false;
533 }
534 sendMessage(LooperMessage::BLOCK_LOOPER);
535 {
536 std::unique_lock lock(mLock);
537 mNotifyLooperWaiting.wait(lock, [this] { return mLooperIsBlocked; });
538 }
539
540 publishMotionEvent(*mPublisher, args);
541
542 // Ensure no event arrives because the UI thread is blocked
543 std::optional<MotionEvent> noEvent = mMotionEvents.popWithTimeout(NO_EVENT_TIMEOUT);
544 ASSERT_FALSE(noEvent.has_value()) << "Got unexpected event: " << *noEvent;
545
546 Result<InputPublisher::ConsumerResponse> result = mPublisher->receiveConsumerResponse();
547 ASSERT_FALSE(result.ok());
548 ASSERT_EQ(WOULD_BLOCK, result.error().code());
549
550 // We shouldn't be calling mConsumer on the UI thread, but in this situation, the looper
551 // thread is locked, so this should be safe to do.
552 ASSERT_TRUE(mConsumer->probablyHasInput())
553 << "should deterministically have input because there is a batch";
554
555 // Now, unblock the looper thread, so that the event can arrive.
556 {
557 std::scoped_lock lock(mLock);
558 mLooperMayProceed = true;
559 }
560 mNotifyLooperMayProceed.notify_all();
561
562 std::optional<MotionEvent> motion = mMotionEvents.popWithTimeout(TIMEOUT);
563 ASSERT_TRUE(motion.has_value());
564 ASSERT_EQ(ACTION_MOVE, motion->getAction());
565
566 verifyFinishedSignal(*mPublisher, seq, publishTime);
567}
568
569void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionEvent(
570 int32_t action, nsecs_t downTime, const std::vector<Pointer>& pointers) {
571 uint32_t seq = mSeq++;
572 PublishMotionArgs args(action, downTime, pointers, seq);
573 nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
574 publishMotionEvent(*mPublisher, args);
575
576 std::optional<MotionEvent> event = mMotionEvents.popWithTimeout(TIMEOUT);
577 ASSERT_TRUE(event.has_value()) << "consumer should have returned non-NULL event";
578
579 verifyArgsEqualToEvent(args, *event);
580
581 verifyFinishedSignal(*mPublisher, seq, publishTime);
582}
583
584void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeFocusEvent() {
585 status_t status;
586
587 constexpr uint32_t seq = 15;
588 int32_t eventId = InputEvent::nextId();
589 constexpr bool hasFocus = true;
590 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
591
592 status = mPublisher->publishFocusEvent(seq, eventId, hasFocus);
593 ASSERT_EQ(OK, status) << "publisher publishFocusEvent should return OK";
594
595 std::optional<FocusEvent> focusEvent = mFocusEvents.popWithTimeout(TIMEOUT);
596 ASSERT_TRUE(focusEvent.has_value()) << "consumer should have returned non-NULL event";
597 EXPECT_EQ(eventId, focusEvent->getId());
598 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
599
600 verifyFinishedSignal(*mPublisher, seq, publishTime);
601}
602
603void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeCaptureEvent() {
604 status_t status;
605
606 constexpr uint32_t seq = 42;
607 int32_t eventId = InputEvent::nextId();
608 constexpr bool captureEnabled = true;
609 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
610
611 status = mPublisher->publishCaptureEvent(seq, eventId, captureEnabled);
612 ASSERT_EQ(OK, status) << "publisher publishCaptureEvent should return OK";
613
614 std::optional<CaptureEvent> event = mCaptureEvents.popWithTimeout(TIMEOUT);
615
616 ASSERT_TRUE(event.has_value()) << "consumer should have returned non-NULL event";
617
618 const CaptureEvent& captureEvent = *event;
619 EXPECT_EQ(eventId, captureEvent.getId());
620 EXPECT_EQ(captureEnabled, captureEvent.getPointerCaptureEnabled());
621
622 verifyFinishedSignal(*mPublisher, seq, publishTime);
623}
624
625void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeDragEvent() {
626 status_t status;
627
628 constexpr uint32_t seq = 15;
629 int32_t eventId = InputEvent::nextId();
630 constexpr bool isExiting = false;
631 constexpr float x = 10;
632 constexpr float y = 15;
633 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
634
635 status = mPublisher->publishDragEvent(seq, eventId, x, y, isExiting);
636 ASSERT_EQ(OK, status) << "publisher publishDragEvent should return OK";
637
638 std::optional<DragEvent> event = mDragEvents.popWithTimeout(TIMEOUT);
639
640 ASSERT_TRUE(event.has_value()) << "consumer should have returned non-NULL event";
641
642 const DragEvent& dragEvent = *event;
643 EXPECT_EQ(eventId, dragEvent.getId());
644 EXPECT_EQ(isExiting, dragEvent.isExiting());
645 EXPECT_EQ(x, dragEvent.getX());
646 EXPECT_EQ(y, dragEvent.getY());
647
648 verifyFinishedSignal(*mPublisher, seq, publishTime);
649}
650
651void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeTouchModeEvent() {
652 status_t status;
653
654 constexpr uint32_t seq = 15;
655 int32_t eventId = InputEvent::nextId();
656 constexpr bool touchModeEnabled = true;
657 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
658
659 status = mPublisher->publishTouchModeEvent(seq, eventId, touchModeEnabled);
660 ASSERT_EQ(OK, status) << "publisher publishTouchModeEvent should return OK";
661
662 std::optional<TouchModeEvent> event = mTouchModeEvents.popWithTimeout(TIMEOUT);
663 ASSERT_NE(std::nullopt, event);
664
665 const TouchModeEvent& touchModeEvent = *event;
666 EXPECT_EQ(eventId, touchModeEvent.getId());
667 EXPECT_EQ(touchModeEnabled, touchModeEvent.isInTouchMode());
668
669 verifyFinishedSignal(*mPublisher, seq, publishTime);
670}
671
672TEST_F(InputPublisherAndConsumerNoResamplingTest, SendTimeline) {
673 const int32_t inputEventId = 20;
674 const nsecs_t gpuCompletedTime = 30;
675 const nsecs_t presentTime = 40;
676
677 mReportTimelineArgs.emplace(inputEventId, gpuCompletedTime, presentTime);
678 sendMessage(LooperMessage::CALL_REPORT_TIMELINE);
679
680 Result<InputPublisher::ConsumerResponse> result = receiveConsumerResponse(*mPublisher, TIMEOUT);
681 ASSERT_TRUE(result.ok()) << "receiveConsumerResponse should return OK";
682 ASSERT_TRUE(std::holds_alternative<InputPublisher::Timeline>(*result));
683 const InputPublisher::Timeline& timeline = std::get<InputPublisher::Timeline>(*result);
684 ASSERT_EQ(inputEventId, timeline.inputEventId);
685 ASSERT_EQ(gpuCompletedTime, timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME]);
686 ASSERT_EQ(presentTime, timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
687}
688
689TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishKeyEvent_EndToEnd) {
690 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
691}
692
693TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMotionEvent_EndToEnd) {
694 ASSERT_NO_FATAL_FAILURE(publishAndConsumeMotionStream());
695}
696
697TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMotionMoveEvent_EndToEnd) {
698 // Publish a DOWN event before MOVE to pass the InputVerifier checks.
699 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
700 ASSERT_NO_FATAL_FAILURE(publishAndConsumeMotionDown(downTime));
701
702 // Publish the MOVE event and check expectations.
703 ASSERT_NO_FATAL_FAILURE(publishAndConsumeBatchedMotionMove(downTime));
704}
705
706TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishFocusEvent_EndToEnd) {
707 ASSERT_NO_FATAL_FAILURE(publishAndConsumeFocusEvent());
708}
709
710TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishCaptureEvent_EndToEnd) {
711 ASSERT_NO_FATAL_FAILURE(publishAndConsumeCaptureEvent());
712}
713
714TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishDragEvent_EndToEnd) {
715 ASSERT_NO_FATAL_FAILURE(publishAndConsumeDragEvent());
716}
717
718TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishTouchModeEvent_EndToEnd) {
719 ASSERT_NO_FATAL_FAILURE(publishAndConsumeTouchModeEvent());
720}
721
722TEST_F(InputPublisherAndConsumerNoResamplingTest,
723 PublishMotionEvent_WhenSequenceNumberIsZero_ReturnsError) {
724 status_t status;
725 const size_t pointerCount = 1;
726 PointerProperties pointerProperties[pointerCount];
727 PointerCoords pointerCoords[pointerCount];
728 for (size_t i = 0; i < pointerCount; i++) {
729 pointerProperties[i].clear();
730 pointerCoords[i].clear();
731 }
732
733 ui::Transform identityTransform;
734 status =
735 mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
736 0, 0, 0, MotionClassification::NONE, identityTransform,
737 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
738 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
739 0, 0, pointerCount, pointerProperties, pointerCoords);
740 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
741}
742
743TEST_F(InputPublisherAndConsumerNoResamplingTest,
744 PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
745 status_t status;
746 const size_t pointerCount = 0;
747 PointerProperties pointerProperties[pointerCount];
748 PointerCoords pointerCoords[pointerCount];
749
750 ui::Transform identityTransform;
751 status =
752 mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
753 0, 0, 0, MotionClassification::NONE, identityTransform,
754 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
755 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
756 0, 0, pointerCount, pointerProperties, pointerCoords);
757 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
758}
759
760TEST_F(InputPublisherAndConsumerNoResamplingTest,
761 PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
762 status_t status;
763 const size_t pointerCount = MAX_POINTERS + 1;
764 PointerProperties pointerProperties[pointerCount];
765 PointerCoords pointerCoords[pointerCount];
766 for (size_t i = 0; i < pointerCount; i++) {
767 pointerProperties[i].clear();
768 pointerCoords[i].clear();
769 }
770
771 ui::Transform identityTransform;
772 status =
773 mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
774 0, 0, 0, MotionClassification::NONE, identityTransform,
775 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
776 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
777 0, 0, pointerCount, pointerProperties, pointerCoords);
778 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
779}
780
781TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMultipleEvents_EndToEnd) {
782 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
783
784 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_DOWN, downTime,
785 {Pointer{.id = 0, .x = 20, .y = 30}});
786 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
787 publishAndConsumeMotionEvent(POINTER_1_DOWN, downTime,
788 {Pointer{.id = 0, .x = 20, .y = 30},
789 Pointer{.id = 1, .x = 200, .y = 300}});
790 ASSERT_NO_FATAL_FAILURE(publishAndConsumeFocusEvent());
791 publishAndConsumeMotionEvent(POINTER_2_DOWN, downTime,
792 {Pointer{.id = 0, .x = 20, .y = 30},
793 Pointer{.id = 1, .x = 200, .y = 300},
794 Pointer{.id = 2, .x = 200, .y = 300}});
795 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
796 ASSERT_NO_FATAL_FAILURE(publishAndConsumeCaptureEvent());
797 ASSERT_NO_FATAL_FAILURE(publishAndConsumeDragEvent());
798 // Provide a consistent input stream - cancel the gesture that was started above
799 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_CANCEL, downTime,
800 {Pointer{.id = 0, .x = 20, .y = 30},
801 Pointer{.id = 1, .x = 200, .y = 300},
802 Pointer{.id = 2, .x = 200, .y = 300}});
803 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
804 ASSERT_NO_FATAL_FAILURE(publishAndConsumeTouchModeEvent());
805}
806
807} // namespace android