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