blob: 1210f711dec7d9cb0a61130180af0daa7e3e0d0a [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 }
Paul Ramirez00cf5d02024-09-05 17:10:12 +0000367 mConsumer->consumeBatchedInputEvents(/*frameTime=*/std::nullopt);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800368 };
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: {
Paul Ramirezbe9c5442024-07-10 00:12:41 +0000399 mConsumer =
400 std::make_unique<InputConsumerNoResampling>(std::move(mClientChannel), mLooper,
401 *this, /*resampler=*/nullptr);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800402 break;
403 }
404 case LooperMessage::DESTROY_CONSUMER: {
405 mConsumer = nullptr;
406 {
407 std::unique_lock lock(mLock);
408 mConsumerDestroyed = true;
409 }
410 mNotifyConsumerDestroyed.notify_all();
411 break;
412 }
413 case LooperMessage::CALL_REPORT_TIMELINE: {
414 std::optional<ReportTimelineArgs> args = mReportTimelineArgs.pop();
415 if (!args.has_value()) {
416 ADD_FAILURE() << "Couldn't get the 'reportTimeline' args in time";
417 return;
418 }
419 mConsumer->reportTimeline(args->inputEventId, args->gpuCompletedTime,
420 args->presentTime);
421 break;
422 }
423 case LooperMessage::BLOCK_LOOPER: {
424 {
425 std::unique_lock lock(mLock);
426 mLooperIsBlocked = true;
427 }
428 mNotifyLooperWaiting.notify_all();
429
430 {
431 std::unique_lock lock(mLock);
432 base::ScopedLockAssertion assumeLocked(mLock);
433 mNotifyLooperMayProceed.wait(lock, [this] { return mLooperMayProceed; });
434 }
435
436 {
437 std::unique_lock lock(mLock);
438 mLooperIsBlocked = false;
439 }
440 mNotifyLooperWaiting.notify_all();
441 break;
442 }
443 }
444}
445
446void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeKeyEvent() {
447 status_t status;
448
449 const uint32_t seq = mSeq++;
450 int32_t eventId = InputEvent::nextId();
451 constexpr int32_t deviceId = 1;
452 constexpr uint32_t source = AINPUT_SOURCE_KEYBOARD;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700453 constexpr ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT;
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800454 constexpr std::array<uint8_t, 32> hmac = {31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21,
455 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,
456 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
457 constexpr int32_t action = AKEY_EVENT_ACTION_DOWN;
458 constexpr int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM;
459 constexpr int32_t keyCode = AKEYCODE_ENTER;
460 constexpr int32_t scanCode = 13;
461 constexpr int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
462 constexpr int32_t repeatCount = 1;
463 constexpr nsecs_t downTime = 3;
464 constexpr nsecs_t eventTime = 4;
465 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
466
467 status = mPublisher->publishKeyEvent(seq, eventId, deviceId, source, displayId, hmac, action,
468 flags, keyCode, scanCode, metaState, repeatCount, downTime,
469 eventTime);
470 ASSERT_EQ(OK, status) << "publisher publishKeyEvent should return OK";
471
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700472 std::optional<std::unique_ptr<KeyEvent>> optKeyEvent = mKeyEvents.popWithTimeout(TIMEOUT);
473 ASSERT_TRUE(optKeyEvent.has_value()) << "consumer should have returned non-NULL event";
474 std::unique_ptr<KeyEvent> keyEvent = std::move(*optKeyEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800475
476 sendMessage(LooperMessage::CALL_PROBABLY_HAS_INPUT);
477 std::optional<bool> probablyHasInput = mProbablyHasInputResponses.popWithTimeout(TIMEOUT);
478 ASSERT_TRUE(probablyHasInput.has_value());
479 ASSERT_FALSE(probablyHasInput.value()) << "no events should be waiting after being consumed";
480
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800481 EXPECT_EQ(eventId, keyEvent->getId());
482 EXPECT_EQ(deviceId, keyEvent->getDeviceId());
483 EXPECT_EQ(source, keyEvent->getSource());
484 EXPECT_EQ(displayId, keyEvent->getDisplayId());
485 EXPECT_EQ(hmac, keyEvent->getHmac());
486 EXPECT_EQ(action, keyEvent->getAction());
487 EXPECT_EQ(flags, keyEvent->getFlags());
488 EXPECT_EQ(keyCode, keyEvent->getKeyCode());
489 EXPECT_EQ(scanCode, keyEvent->getScanCode());
490 EXPECT_EQ(metaState, keyEvent->getMetaState());
491 EXPECT_EQ(repeatCount, keyEvent->getRepeatCount());
492 EXPECT_EQ(downTime, keyEvent->getDownTime());
493 EXPECT_EQ(eventTime, keyEvent->getEventTime());
494
495 verifyFinishedSignal(*mPublisher, seq, publishTime);
496}
497
498void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionStream() {
499 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
500
501 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_DOWN, downTime,
502 {Pointer{.id = 0, .x = 20, .y = 30}});
503
504 publishAndConsumeMotionEvent(POINTER_1_DOWN, downTime,
505 {Pointer{.id = 0, .x = 20, .y = 30},
506 Pointer{.id = 1, .x = 200, .y = 300}});
507
508 publishAndConsumeMotionEvent(POINTER_2_DOWN, downTime,
509 {Pointer{.id = 0, .x = 20, .y = 30},
510 Pointer{.id = 1, .x = 200, .y = 300},
511 Pointer{.id = 2, .x = 300, .y = 400}});
512
513 // Provide a consistent input stream - cancel the gesture that was started above
514 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_CANCEL, downTime,
515 {Pointer{.id = 0, .x = 20, .y = 30},
516 Pointer{.id = 1, .x = 200, .y = 300},
517 Pointer{.id = 2, .x = 300, .y = 400}});
518}
519
520void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionDown(nsecs_t downTime) {
521 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_DOWN, downTime,
522 {Pointer{.id = 0, .x = 20, .y = 30}});
523}
524
Paul Ramirez79655f22024-07-01 21:55:48 +0000525/*
526 * Decompose a potential multi-sampled MotionEvent into multiple MotionEvents
527 * with a single sample.
528 */
529std::vector<MotionEvent> splitBatchedMotionEvent(const MotionEvent& batchedMotionEvent) {
530 std::vector<MotionEvent> singleMotionEvents;
531 const size_t batchSize = batchedMotionEvent.getHistorySize() + 1;
532 for (size_t i = 0; i < batchSize; ++i) {
533 MotionEvent singleMotionEvent;
534 singleMotionEvent
535 .initialize(batchedMotionEvent.getId(), batchedMotionEvent.getDeviceId(),
536 batchedMotionEvent.getSource(), batchedMotionEvent.getDisplayId(),
537 batchedMotionEvent.getHmac(), batchedMotionEvent.getAction(),
538 batchedMotionEvent.getActionButton(), batchedMotionEvent.getFlags(),
539 batchedMotionEvent.getEdgeFlags(), batchedMotionEvent.getMetaState(),
540 batchedMotionEvent.getButtonState(),
541 batchedMotionEvent.getClassification(),
542 batchedMotionEvent.getTransform(), batchedMotionEvent.getXPrecision(),
543 batchedMotionEvent.getYPrecision(),
544 batchedMotionEvent.getRawXCursorPosition(),
545 batchedMotionEvent.getRawYCursorPosition(),
546 batchedMotionEvent.getRawTransform(), batchedMotionEvent.getDownTime(),
547 batchedMotionEvent.getHistoricalEventTime(/*historicalIndex=*/i),
548 batchedMotionEvent.getPointerCount(),
549 batchedMotionEvent.getPointerProperties(),
550 (batchedMotionEvent.getSamplePointerCoords() + i));
551 singleMotionEvents.push_back(singleMotionEvent);
552 }
553 return singleMotionEvents;
554}
555
556/*
557 * Simulates a single pointer touching the screen and leaving it there for a period of time.
558 * Publishes a DOWN event and consumes it right away. Then, publishes a sequence of MOVE
559 * samples for the same pointer, and waits until it has been consumed. Splits batched MotionEvents
560 * into individual samples. Checks the consumed MotionEvents against the published ones.
561 * This test is non-deterministic because it depends on the timing of arrival of events to the
562 * socket.
563 *
564 * @param nSamples The number of MOVE samples to publish before attempting consumption.
565 */
566void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeSinglePointerMultipleSamples(
567 const size_t nSamples) {
568 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
569 const Pointer pointer(0, 20, 30);
570
571 const PublishMotionArgs argsDown(AMOTION_EVENT_ACTION_DOWN, downTime, {pointer}, mSeq);
572 const nsecs_t publishTimeOfDown = systemTime(SYSTEM_TIME_MONOTONIC);
573 publishMotionEvent(*mPublisher, argsDown);
574
575 // Consume the DOWN event.
576 ASSERT_TRUE(mMotionEvents.popWithTimeout(TIMEOUT).has_value());
577
578 verifyFinishedSignal(*mPublisher, mSeq, publishTimeOfDown);
579
580 std::vector<nsecs_t> publishTimes;
581 std::vector<PublishMotionArgs> argsMoves;
582 std::queue<uint32_t> publishedSequenceNumbers;
583
584 // Block Looper to increase the chance of batching events
585 {
586 std::scoped_lock l(mLock);
587 mLooperMayProceed = false;
588 }
589 sendMessage(LooperMessage::BLOCK_LOOPER);
590 {
591 std::unique_lock l(mLock);
592 mNotifyLooperWaiting.wait(l, [this] { return mLooperIsBlocked; });
593 }
594
595 uint32_t firstSampleId;
596 for (size_t i = 0; i < nSamples; ++i) {
597 publishedSequenceNumbers.push(++mSeq);
598 PublishMotionArgs argsMove(AMOTION_EVENT_ACTION_MOVE, downTime, {pointer}, mSeq);
599 // A batched MotionEvent only has a single event id, currently determined when the
600 // MotionEvent is initialized. Therefore, to pass the eventId comparisons inside
601 // verifyArgsEqualToEvent, we need to override the event id of the published args to match
602 // the event id of the first sample inside the MotionEvent.
603 if (i == 0) {
604 firstSampleId = argsMove.eventId;
605 }
606 argsMove.eventId = firstSampleId;
607 publishTimes.push_back(systemTime(SYSTEM_TIME_MONOTONIC));
608 argsMoves.push_back(argsMove);
609 publishMotionEvent(*mPublisher, argsMove);
610 }
611
612 std::vector<MotionEvent> singleSampledMotionEvents;
613
614 // Unblock Looper
615 {
616 std::scoped_lock l(mLock);
617 mLooperMayProceed = true;
618 }
619 mNotifyLooperMayProceed.notify_all();
620
621 // We have no control over the socket behavior, so the consumer can receive
622 // the motion as a batched event, or as a sequence of multiple single-sample MotionEvents (or a
623 // mix of those)
624 while (singleSampledMotionEvents.size() != nSamples) {
625 const std::optional<std::unique_ptr<MotionEvent>> batchedMotionEvent =
626 mMotionEvents.popWithTimeout(TIMEOUT);
627 // The events received by these calls are never null
628 std::vector<MotionEvent> splitMotionEvents = splitBatchedMotionEvent(**batchedMotionEvent);
629 singleSampledMotionEvents.insert(singleSampledMotionEvents.end(), splitMotionEvents.begin(),
630 splitMotionEvents.end());
631 }
632
633 // Consumer can choose to finish events in any order. For simplicity,
634 // we verify the events in sequence (since that is how the test is implemented).
635 for (size_t i = 0; i < nSamples; ++i) {
636 verifyArgsEqualToEvent(argsMoves[i], singleSampledMotionEvents[i]);
637 verifyFinishedSignal(*mPublisher, publishedSequenceNumbers.front(), publishTimes[i]);
638 publishedSequenceNumbers.pop();
639 }
640}
641
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800642void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeBatchedMotionMove(
643 nsecs_t downTime) {
644 uint32_t seq = mSeq++;
645 const std::vector<Pointer> pointers = {Pointer{.id = 0, .x = 20, .y = 30}};
646 PublishMotionArgs args(AMOTION_EVENT_ACTION_MOVE, downTime, pointers, seq);
647 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
648
649 // Block the looper thread, preventing it from being able to service any of the fd callbacks.
650
651 {
652 std::scoped_lock lock(mLock);
653 mLooperMayProceed = false;
654 }
655 sendMessage(LooperMessage::BLOCK_LOOPER);
656 {
657 std::unique_lock lock(mLock);
658 mNotifyLooperWaiting.wait(lock, [this] { return mLooperIsBlocked; });
659 }
660
661 publishMotionEvent(*mPublisher, args);
662
663 // Ensure no event arrives because the UI thread is blocked
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700664 std::optional<std::unique_ptr<MotionEvent>> noEvent =
665 mMotionEvents.popWithTimeout(NO_EVENT_TIMEOUT);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800666 ASSERT_FALSE(noEvent.has_value()) << "Got unexpected event: " << *noEvent;
667
668 Result<InputPublisher::ConsumerResponse> result = mPublisher->receiveConsumerResponse();
669 ASSERT_FALSE(result.ok());
670 ASSERT_EQ(WOULD_BLOCK, result.error().code());
671
672 // We shouldn't be calling mConsumer on the UI thread, but in this situation, the looper
673 // thread is locked, so this should be safe to do.
674 ASSERT_TRUE(mConsumer->probablyHasInput())
675 << "should deterministically have input because there is a batch";
676
677 // Now, unblock the looper thread, so that the event can arrive.
678 {
679 std::scoped_lock lock(mLock);
680 mLooperMayProceed = true;
681 }
682 mNotifyLooperMayProceed.notify_all();
683
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700684 std::optional<std::unique_ptr<MotionEvent>> optMotion = mMotionEvents.popWithTimeout(TIMEOUT);
685 ASSERT_TRUE(optMotion.has_value());
686 std::unique_ptr<MotionEvent> motion = std::move(*optMotion);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800687 ASSERT_EQ(ACTION_MOVE, motion->getAction());
688
689 verifyFinishedSignal(*mPublisher, seq, publishTime);
690}
691
692void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeMotionEvent(
693 int32_t action, nsecs_t downTime, const std::vector<Pointer>& pointers) {
694 uint32_t seq = mSeq++;
695 PublishMotionArgs args(action, downTime, pointers, seq);
696 nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
697 publishMotionEvent(*mPublisher, args);
698
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700699 std::optional<std::unique_ptr<MotionEvent>> optMotion = mMotionEvents.popWithTimeout(TIMEOUT);
700 ASSERT_TRUE(optMotion.has_value());
701 std::unique_ptr<MotionEvent> event = std::move(*optMotion);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800702
703 verifyArgsEqualToEvent(args, *event);
704
705 verifyFinishedSignal(*mPublisher, seq, publishTime);
706}
707
708void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeFocusEvent() {
709 status_t status;
710
711 constexpr uint32_t seq = 15;
712 int32_t eventId = InputEvent::nextId();
713 constexpr bool hasFocus = true;
714 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
715
716 status = mPublisher->publishFocusEvent(seq, eventId, hasFocus);
717 ASSERT_EQ(OK, status) << "publisher publishFocusEvent should return OK";
718
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700719 std::optional<std::unique_ptr<FocusEvent>> optFocusEvent = mFocusEvents.popWithTimeout(TIMEOUT);
720 ASSERT_TRUE(optFocusEvent.has_value()) << "consumer should have returned non-NULL event";
721 std::unique_ptr<FocusEvent> focusEvent = std::move(*optFocusEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800722 EXPECT_EQ(eventId, focusEvent->getId());
723 EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
724
725 verifyFinishedSignal(*mPublisher, seq, publishTime);
726}
727
728void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeCaptureEvent() {
729 status_t status;
730
731 constexpr uint32_t seq = 42;
732 int32_t eventId = InputEvent::nextId();
733 constexpr bool captureEnabled = true;
734 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
735
736 status = mPublisher->publishCaptureEvent(seq, eventId, captureEnabled);
737 ASSERT_EQ(OK, status) << "publisher publishCaptureEvent should return OK";
738
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700739 std::optional<std::unique_ptr<CaptureEvent>> optEvent = mCaptureEvents.popWithTimeout(TIMEOUT);
740 ASSERT_TRUE(optEvent.has_value()) << "consumer should have returned non-NULL event";
741 std::unique_ptr<CaptureEvent> event = std::move(*optEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800742
743 const CaptureEvent& captureEvent = *event;
744 EXPECT_EQ(eventId, captureEvent.getId());
745 EXPECT_EQ(captureEnabled, captureEvent.getPointerCaptureEnabled());
746
747 verifyFinishedSignal(*mPublisher, seq, publishTime);
748}
749
750void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeDragEvent() {
751 status_t status;
752
753 constexpr uint32_t seq = 15;
754 int32_t eventId = InputEvent::nextId();
755 constexpr bool isExiting = false;
756 constexpr float x = 10;
757 constexpr float y = 15;
758 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
759
760 status = mPublisher->publishDragEvent(seq, eventId, x, y, isExiting);
761 ASSERT_EQ(OK, status) << "publisher publishDragEvent should return OK";
762
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700763 std::optional<std::unique_ptr<DragEvent>> optEvent = mDragEvents.popWithTimeout(TIMEOUT);
764 ASSERT_TRUE(optEvent.has_value()) << "consumer should have returned non-NULL event";
765 std::unique_ptr<DragEvent> event = std::move(*optEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800766
767 const DragEvent& dragEvent = *event;
768 EXPECT_EQ(eventId, dragEvent.getId());
769 EXPECT_EQ(isExiting, dragEvent.isExiting());
770 EXPECT_EQ(x, dragEvent.getX());
771 EXPECT_EQ(y, dragEvent.getY());
772
773 verifyFinishedSignal(*mPublisher, seq, publishTime);
774}
775
776void InputPublisherAndConsumerNoResamplingTest::publishAndConsumeTouchModeEvent() {
777 status_t status;
778
779 constexpr uint32_t seq = 15;
780 int32_t eventId = InputEvent::nextId();
781 constexpr bool touchModeEnabled = true;
782 const nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
783
784 status = mPublisher->publishTouchModeEvent(seq, eventId, touchModeEnabled);
785 ASSERT_EQ(OK, status) << "publisher publishTouchModeEvent should return OK";
786
Siarhei Vishniakou3891ec92024-03-15 13:29:57 -0700787 std::optional<std::unique_ptr<TouchModeEvent>> optEvent =
788 mTouchModeEvents.popWithTimeout(TIMEOUT);
789 ASSERT_TRUE(optEvent.has_value());
790 std::unique_ptr<TouchModeEvent> event = std::move(*optEvent);
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800791
792 const TouchModeEvent& touchModeEvent = *event;
793 EXPECT_EQ(eventId, touchModeEvent.getId());
794 EXPECT_EQ(touchModeEnabled, touchModeEvent.isInTouchMode());
795
796 verifyFinishedSignal(*mPublisher, seq, publishTime);
797}
798
799TEST_F(InputPublisherAndConsumerNoResamplingTest, SendTimeline) {
800 const int32_t inputEventId = 20;
801 const nsecs_t gpuCompletedTime = 30;
802 const nsecs_t presentTime = 40;
803
804 mReportTimelineArgs.emplace(inputEventId, gpuCompletedTime, presentTime);
805 sendMessage(LooperMessage::CALL_REPORT_TIMELINE);
806
807 Result<InputPublisher::ConsumerResponse> result = receiveConsumerResponse(*mPublisher, TIMEOUT);
808 ASSERT_TRUE(result.ok()) << "receiveConsumerResponse should return OK";
809 ASSERT_TRUE(std::holds_alternative<InputPublisher::Timeline>(*result));
810 const InputPublisher::Timeline& timeline = std::get<InputPublisher::Timeline>(*result);
811 ASSERT_EQ(inputEventId, timeline.inputEventId);
812 ASSERT_EQ(gpuCompletedTime, timeline.graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME]);
813 ASSERT_EQ(presentTime, timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME]);
814}
815
816TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishKeyEvent_EndToEnd) {
817 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
818}
819
820TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMotionEvent_EndToEnd) {
821 ASSERT_NO_FATAL_FAILURE(publishAndConsumeMotionStream());
822}
823
824TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMotionMoveEvent_EndToEnd) {
825 // Publish a DOWN event before MOVE to pass the InputVerifier checks.
826 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
827 ASSERT_NO_FATAL_FAILURE(publishAndConsumeMotionDown(downTime));
828
829 // Publish the MOVE event and check expectations.
830 ASSERT_NO_FATAL_FAILURE(publishAndConsumeBatchedMotionMove(downTime));
831}
832
833TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishFocusEvent_EndToEnd) {
834 ASSERT_NO_FATAL_FAILURE(publishAndConsumeFocusEvent());
835}
836
837TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishCaptureEvent_EndToEnd) {
838 ASSERT_NO_FATAL_FAILURE(publishAndConsumeCaptureEvent());
839}
840
841TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishDragEvent_EndToEnd) {
842 ASSERT_NO_FATAL_FAILURE(publishAndConsumeDragEvent());
843}
844
845TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishTouchModeEvent_EndToEnd) {
846 ASSERT_NO_FATAL_FAILURE(publishAndConsumeTouchModeEvent());
847}
848
849TEST_F(InputPublisherAndConsumerNoResamplingTest,
850 PublishMotionEvent_WhenSequenceNumberIsZero_ReturnsError) {
851 status_t status;
852 const size_t pointerCount = 1;
853 PointerProperties pointerProperties[pointerCount];
854 PointerCoords pointerCoords[pointerCount];
855 for (size_t i = 0; i < pointerCount; i++) {
856 pointerProperties[i].clear();
857 pointerCoords[i].clear();
858 }
859
860 ui::Transform identityTransform;
861 status =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700862 mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0,
863 ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
864 0, 0, MotionClassification::NONE, identityTransform, 0,
865 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800866 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
867 0, 0, pointerCount, pointerProperties, pointerCoords);
868 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
869}
870
871TEST_F(InputPublisherAndConsumerNoResamplingTest,
872 PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
873 status_t status;
874 const size_t pointerCount = 0;
875 PointerProperties pointerProperties[pointerCount];
876 PointerCoords pointerCoords[pointerCount];
877
878 ui::Transform identityTransform;
879 status =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700880 mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0,
881 ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
882 0, 0, MotionClassification::NONE, identityTransform, 0,
883 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800884 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
885 0, 0, pointerCount, pointerProperties, pointerCoords);
886 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
887}
888
889TEST_F(InputPublisherAndConsumerNoResamplingTest,
890 PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
891 status_t status;
892 const size_t pointerCount = MAX_POINTERS + 1;
893 PointerProperties pointerProperties[pointerCount];
894 PointerCoords pointerCoords[pointerCount];
895 for (size_t i = 0; i < pointerCount; i++) {
896 pointerProperties[i].clear();
897 pointerCoords[i].clear();
898 }
899
900 ui::Transform identityTransform;
901 status =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700902 mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0,
903 ui::LogicalDisplayId::DEFAULT, INVALID_HMAC, 0, 0, 0, 0,
904 0, 0, MotionClassification::NONE, identityTransform, 0,
905 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800906 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
907 0, 0, pointerCount, pointerProperties, pointerCoords);
908 ASSERT_EQ(BAD_VALUE, status) << "publisher publishMotionEvent should return BAD_VALUE";
909}
910
911TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishMultipleEvents_EndToEnd) {
912 const nsecs_t downTime = systemTime(SYSTEM_TIME_MONOTONIC);
913
914 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_DOWN, downTime,
915 {Pointer{.id = 0, .x = 20, .y = 30}});
916 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
917 publishAndConsumeMotionEvent(POINTER_1_DOWN, downTime,
918 {Pointer{.id = 0, .x = 20, .y = 30},
919 Pointer{.id = 1, .x = 200, .y = 300}});
920 ASSERT_NO_FATAL_FAILURE(publishAndConsumeFocusEvent());
921 publishAndConsumeMotionEvent(POINTER_2_DOWN, downTime,
922 {Pointer{.id = 0, .x = 20, .y = 30},
923 Pointer{.id = 1, .x = 200, .y = 300},
924 Pointer{.id = 2, .x = 200, .y = 300}});
925 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
926 ASSERT_NO_FATAL_FAILURE(publishAndConsumeCaptureEvent());
927 ASSERT_NO_FATAL_FAILURE(publishAndConsumeDragEvent());
928 // Provide a consistent input stream - cancel the gesture that was started above
929 publishAndConsumeMotionEvent(AMOTION_EVENT_ACTION_CANCEL, downTime,
930 {Pointer{.id = 0, .x = 20, .y = 30},
931 Pointer{.id = 1, .x = 200, .y = 300},
932 Pointer{.id = 2, .x = 200, .y = 300}});
933 ASSERT_NO_FATAL_FAILURE(publishAndConsumeKeyEvent());
934 ASSERT_NO_FATAL_FAILURE(publishAndConsumeTouchModeEvent());
935}
936
Paul Ramirez79655f22024-07-01 21:55:48 +0000937TEST_F(InputPublisherAndConsumerNoResamplingTest, PublishAndConsumeSinglePointer) {
938 publishAndConsumeSinglePointerMultipleSamples(3);
939}
940
Siarhei Vishniakou2b920272024-02-27 19:49:51 -0800941} // namespace android