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