blob: 65934977636c58a8951916bb74ff8c9c07e08d78 [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
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700344 BlockingQueue<std::unique_ptr<KeyEvent>> mKeyEvents;
345 BlockingQueue<std::unique_ptr<MotionEvent>> mMotionEvents;
346 BlockingQueue<std::unique_ptr<FocusEvent>> mFocusEvents;
347 BlockingQueue<std::unique_ptr<CaptureEvent>> mCaptureEvents;
348 BlockingQueue<std::unique_ptr<DragEvent>> mDragEvents;
349 BlockingQueue<std::unique_ptr<TouchModeEvent>> mTouchModeEvents;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800350
351 // InputConsumerCallbacks interface
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700352 void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800353 mKeyEvents.push(std::move(event));
354 mConsumer->finishInputEvent(seq, true);
355 }
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700356 void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800357 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 };
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700366 void onFocusEvent(std::unique_ptr<FocusEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800367 mFocusEvents.push(std::move(event));
368 mConsumer->finishInputEvent(seq, true);
369 };
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700370 void onCaptureEvent(std::unique_ptr<CaptureEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800371 mCaptureEvents.push(std::move(event));
372 mConsumer->finishInputEvent(seq, true);
373 };
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700374 void onDragEvent(std::unique_ptr<DragEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800375 mDragEvents.push(std::move(event));
376 mConsumer->finishInputEvent(seq, true);
377 }
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700378 void onTouchModeEvent(std::unique_ptr<TouchModeEvent> event, uint32_t seq) override {
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800379 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
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700468 std::optional<std::unique_ptr<KeyEvent>> optKeyEvent = mKeyEvents.popWithTimeout(TIMEOUT);
469 ASSERT_TRUE(optKeyEvent.has_value()) << "consumer should have returned non-NULL event";
470 std::unique_ptr<KeyEvent> keyEvent = std::move(*optKeyEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800471
472 sendMessage(LooperMessage::CALL_PROBABLY_HAS_INPUT);
473 std::optional<bool> probablyHasInput = mProbablyHasInputResponses.popWithTimeout(TIMEOUT);
474 ASSERT_TRUE(probablyHasInput.has_value());
475 ASSERT_FALSE(probablyHasInput.value()) << "no events should be waiting after being consumed";
476
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800477 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
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700543 std::optional<std::unique_ptr<MotionEvent>> noEvent =
544 mMotionEvents.popWithTimeout(NO_EVENT_TIMEOUT);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800545 ASSERT_FALSE(noEvent.has_value()) << "Got unexpected event: " << *noEvent;
546
547 Result<InputPublisher::ConsumerResponse> result = mPublisher->receiveConsumerResponse();
548 ASSERT_FALSE(result.ok());
549 ASSERT_EQ(WOULD_BLOCK, result.error().code());
550
551 // We shouldn't be calling mConsumer on the UI thread, but in this situation, the looper
552 // thread is locked, so this should be safe to do.
553 ASSERT_TRUE(mConsumer->probablyHasInput())
554 << "should deterministically have input because there is a batch";
555
556 // Now, unblock the looper thread, so that the event can arrive.
557 {
558 std::scoped_lock lock(mLock);
559 mLooperMayProceed = true;
560 }
561 mNotifyLooperMayProceed.notify_all();
562
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700563 std::optional<std::unique_ptr<MotionEvent>> optMotion = mMotionEvents.popWithTimeout(TIMEOUT);
564 ASSERT_TRUE(optMotion.has_value());
565 std::unique_ptr<MotionEvent> motion = std::move(*optMotion);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800566 ASSERT_EQ(ACTION_MOVE, motion->getAction());
567
568 verifyFinishedSignal(*mPublisher, seq, publishTime);
569}
570
571void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionEvent(
572 int32_t action, nsecs_t downTime, const std::vector<Pointer>& pointers) {
573 uint32_t seq = mSeq++;
574 PublishMotionArgs args(action, downTime, pointers, seq);
575 nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
576 publishMotionEvent(*mPublisher, args);
577
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700578 std::optional<std::unique_ptr<MotionEvent>> optMotion = mMotionEvents.popWithTimeout(TIMEOUT);
579 ASSERT_TRUE(optMotion.has_value());
580 std::unique_ptr<MotionEvent> event = std::move(*optMotion);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800581
582 verifyArgsEqualToEvent(args, *event);
583
584 verifyFinishedSignal(*mPublisher, seq, publishTime);
585}
586
587void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeFocusEvent() {
588 status_t status;
589
590 constexpr uint32_t seq = 15;
591 int32_t eventId = InputEvent::nextId();
592 constexpr bool hasFocus = true;
593 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
594
595 status = mPublisher->publishFocusEvent(seq, eventId, hasFocus);
596 ASSERT_EQ(OK, status) << "publisher publishFocusEvent should return OK";
597
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700598 std::optional<std::unique_ptr<FocusEvent>> optFocusEvent = mFocusEvents.popWithTimeout(TIMEOUT);
599 ASSERT_TRUE(optFocusEvent.has_value()) << "consumer should have returned non-NULL event";
600 std::unique_ptr<FocusEvent> focusEvent = std::move(*optFocusEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800601 EXPECT_EQ(eventId, focusEvent->getId());
602 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
603
604 verifyFinishedSignal(*mPublisher, seq, publishTime);
605}
606
607void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeCaptureEvent() {
608 status_t status;
609
610 constexpr uint32_t seq = 42;
611 int32_t eventId = InputEvent::nextId();
612 constexpr bool captureEnabled = true;
613 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
614
615 status = mPublisher->publishCaptureEvent(seq, eventId, captureEnabled);
616 ASSERT_EQ(OK, status) << "publisher publishCaptureEvent should return OK";
617
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700618 std::optional<std::unique_ptr<CaptureEvent>> optEvent = mCaptureEvents.popWithTimeout(TIMEOUT);
619 ASSERT_TRUE(optEvent.has_value()) << "consumer should have returned non-NULL event";
620 std::unique_ptr<CaptureEvent> event = std::move(*optEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800621
622 const CaptureEvent& captureEvent = *event;
623 EXPECT_EQ(eventId, captureEvent.getId());
624 EXPECT_EQ(captureEnabled, captureEvent.getPointerCaptureEnabled());
625
626 verifyFinishedSignal(*mPublisher, seq, publishTime);
627}
628
629void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeDragEvent() {
630 status_t status;
631
632 constexpr uint32_t seq = 15;
633 int32_t eventId = InputEvent::nextId();
634 constexpr bool isExiting = false;
635 constexpr float x = 10;
636 constexpr float y = 15;
637 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
638
639 status = mPublisher->publishDragEvent(seq, eventId, x, y, isExiting);
640 ASSERT_EQ(OK, status) << "publisher publishDragEvent should return OK";
641
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700642 std::optional<std::unique_ptr<DragEvent>> optEvent = mDragEvents.popWithTimeout(TIMEOUT);
643 ASSERT_TRUE(optEvent.has_value()) << "consumer should have returned non-NULL event";
644 std::unique_ptr<DragEvent> event = std::move(*optEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800645
646 const DragEvent& dragEvent = *event;
647 EXPECT_EQ(eventId, dragEvent.getId());
648 EXPECT_EQ(isExiting, dragEvent.isExiting());
649 EXPECT_EQ(x, dragEvent.getX());
650 EXPECT_EQ(y, dragEvent.getY());
651
652 verifyFinishedSignal(*mPublisher, seq, publishTime);
653}
654
655void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeTouchModeEvent() {
656 status_t status;
657
658 constexpr uint32_t seq = 15;
659 int32_t eventId = InputEvent::nextId();
660 constexpr bool touchModeEnabled = true;
661 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
662
663 status = mPublisher->publishTouchModeEvent(seq, eventId, touchModeEnabled);
664 ASSERT_EQ(OK, status) << "publisher publishTouchModeEvent should return OK";
665
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700666 std::optional<std::unique_ptr<TouchModeEvent>> optEvent =
667 mTouchModeEvents.popWithTimeout(TIMEOUT);
668 ASSERT_TRUE(optEvent.has_value());
669 std::unique_ptr<TouchModeEvent> event = std::move(*optEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800670
671 const TouchModeEvent& touchModeEvent = *event;
672 EXPECT_EQ(eventId, touchModeEvent.getId());
673 EXPECT_EQ(touchModeEnabled, touchModeEvent.isInTouchMode());
674
675 verifyFinishedSignal(*mPublisher, seq, publishTime);
676}
677
678TEST_F(InputPublisherAndConsumerNoResamplingTest, SendTimeline) {
679 const int32_t inputEventId = 20;
680 const nsecs_t gpuCompletedTime = 30;
681 const nsecs_t presentTime = 40;
682
683 mReportTimelineArgs.emplace(inputEventId, gpuCompletedTime, presentTime);
684 sendMessage(LooperMessage::CALL_REPORT_TIMELINE);
685
686 Result<InputPublisher::ConsumerResponse> result = receiveConsumerResponse(*mPublisher, TIMEOUT);
687 ASSERT_TRUE(result.ok()) << "receiveConsumerResponse should return OK";
688 ASSERT_TRUE(std::holds_alternative<InputPublisher::Timeline>(*result));
689 const InputPublisher::Timeline& timeline = std::get<InputPublisher::Timeline>(*result);
690 ASSERT_EQ(inputEventId, timeline.inputEventId);
691 ASSERT_EQ(gpuCompletedTime, timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME]);
692 ASSERT_EQ(presentTime, timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
693}
694
695TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishKeyEvent_EndToEnd) {
696 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
697}
698
699TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMotionEvent_EndToEnd) {
700 ASSERT_NO_FATAL_FAILURE(publishAndConsumeMotionStream());
701}
702
703TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMotionMoveEvent_EndToEnd) {
704 // Publish a DOWN event before MOVE to pass the InputVerifier checks.
705 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
706 ASSERT_NO_FATAL_FAILURE(publishAndConsumeMotionDown(downTime));
707
708 // Publish the MOVE event and check expectations.
709 ASSERT_NO_FATAL_FAILURE(publishAndConsumeBatchedMotionMove(downTime));
710}
711
712TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishFocusEvent_EndToEnd) {
713 ASSERT_NO_FATAL_FAILURE(publishAndConsumeFocusEvent());
714}
715
716TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishCaptureEvent_EndToEnd) {
717 ASSERT_NO_FATAL_FAILURE(publishAndConsumeCaptureEvent());
718}
719
720TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishDragEvent_EndToEnd) {
721 ASSERT_NO_FATAL_FAILURE(publishAndConsumeDragEvent());
722}
723
724TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishTouchModeEvent_EndToEnd) {
725 ASSERT_NO_FATAL_FAILURE(publishAndConsumeTouchModeEvent());
726}
727
728TEST_F(InputPublisherAndConsumerNoResamplingTest,
729 PublishMotionEvent_WhenSequenceNumberIsZero_ReturnsError) {
730 status_t status;
731 const size_t pointerCount = 1;
732 PointerProperties pointerProperties[pointerCount];
733 PointerCoords pointerCoords[pointerCount];
734 for (size_t i = 0; i < pointerCount; i++) {
735 pointerProperties[i].clear();
736 pointerCoords[i].clear();
737 }
738
739 ui::Transform identityTransform;
740 status =
741 mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
742 0, 0, 0, MotionClassification::NONE, identityTransform,
743 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
744 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
745 0, 0, pointerCount, pointerProperties, pointerCoords);
746 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
747}
748
749TEST_F(InputPublisherAndConsumerNoResamplingTest,
750 PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
751 status_t status;
752 const size_t pointerCount = 0;
753 PointerProperties pointerProperties[pointerCount];
754 PointerCoords pointerCoords[pointerCount];
755
756 ui::Transform identityTransform;
757 status =
758 mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
759 0, 0, 0, MotionClassification::NONE, identityTransform,
760 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
761 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
762 0, 0, pointerCount, pointerProperties, pointerCoords);
763 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
764}
765
766TEST_F(InputPublisherAndConsumerNoResamplingTest,
767 PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
768 status_t status;
769 const size_t pointerCount = MAX_POINTERS + 1;
770 PointerProperties pointerProperties[pointerCount];
771 PointerCoords pointerCoords[pointerCount];
772 for (size_t i = 0; i < pointerCount; i++) {
773 pointerProperties[i].clear();
774 pointerCoords[i].clear();
775 }
776
777 ui::Transform identityTransform;
778 status =
779 mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
780 0, 0, 0, MotionClassification::NONE, identityTransform,
781 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
782 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
783 0, 0, pointerCount, pointerProperties, pointerCoords);
784 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
785}
786
787TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMultipleEvents_EndToEnd) {
788 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
789
790 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_DOWN, downTime,
791 {Pointer{.id = 0, .x = 20, .y = 30}});
792 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
793 publishAndConsumeMotionEvent(POINTER_1_DOWN, downTime,
794 {Pointer{.id = 0, .x = 20, .y = 30},
795 Pointer{.id = 1, .x = 200, .y = 300}});
796 ASSERT_NO_FATAL_FAILURE(publishAndConsumeFocusEvent());
797 publishAndConsumeMotionEvent(POINTER_2_DOWN, downTime,
798 {Pointer{.id = 0, .x = 20, .y = 30},
799 Pointer{.id = 1, .x = 200, .y = 300},
800 Pointer{.id = 2, .x = 200, .y = 300}});
801 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
802 ASSERT_NO_FATAL_FAILURE(publishAndConsumeCaptureEvent());
803 ASSERT_NO_FATAL_FAILURE(publishAndConsumeDragEvent());
804 // Provide a consistent input stream - cancel the gesture that was started above
805 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_CANCEL, downTime,
806 {Pointer{.id = 0, .x = 20, .y = 30},
807 Pointer{.id = 1, .x = 200, .y = 300},
808 Pointer{.id = 2, .x = 200, .y = 300}});
809 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
810 ASSERT_NO_FATAL_FAILURE(publishAndConsumeTouchModeEvent());
811}
812
813} // namespace android