blob: 3a3238a6adae82b94a81b2cecbe62252fc74b895 [file] [log] [blame]
Prabir Pradhanc5340732024-03-20 22:53:52 +00001/*
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#pragma once
18
19#include "../dispatcher/InputDispatcher.h"
20#include "TestEventMatchers.h"
21
22#include <android-base/logging.h>
23#include <gtest/gtest.h>
24#include <input/Input.h>
25#include <input/InputConsumer.h>
26
27namespace android {
28
29/**
30 * If we expect to receive the event, the timeout can be made very long. When the test are running
31 * correctly, we will actually never wait until the end of the timeout because the wait will end
32 * when the event comes in. Still, this value shouldn't be infinite. During development, a local
33 * change may cause the test to fail. This timeout should be short enough to not annoy so that the
34 * developer can see the failure quickly (on human scale).
35 */
36static constexpr std::chrono::duration CONSUME_TIMEOUT_EVENT_EXPECTED = 1000ms;
37
38/**
39 * When no event is expected, we can have a very short timeout. A large value here would slow down
40 * the tests. In the unlikely event of system being too slow, the event may still be present but the
41 * timeout would complete before it is consumed. This would result in test flakiness. If this
42 * occurs, the flakiness rate would be high. Since the flakes are treated with high priority, this
43 * would get noticed and addressed quickly.
44 */
45static constexpr std::chrono::duration CONSUME_TIMEOUT_NO_EVENT_EXPECTED = 10ms;
46
47/**
48 * The default pid and uid for windows created on the primary display by the test.
49 */
50static constexpr gui::Pid WINDOW_PID{999};
51static constexpr gui::Uid WINDOW_UID{1001};
52
53/**
54 * Default input dispatching timeout if there is no focused application or paused window
55 * from which to determine an appropriate dispatching timeout.
56 */
57static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
58 android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
59 android::base::HwTimeoutMultiplier());
60
61// --- FakeInputReceiver ---
62
63class FakeInputReceiver {
64public:
65 explicit FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel, const std::string name);
66
67 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = false);
68 /**
69 * Receive an event without acknowledging it.
70 * Return the sequence number that could later be used to send finished signal.
71 */
72 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent(
73 std::chrono::milliseconds timeout);
74 /**
75 * To be used together with "receiveEvent" to complete the consumption of an event.
76 */
77 void finishEvent(uint32_t consumeSeq, bool handled = true);
78
79 void sendTimeline(int32_t inputEventId, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline);
80
81 void consumeEvent(android::InputEventType expectedEventType, int32_t expectedAction,
Linnan Li13bf76a2024-05-05 19:18:02 +080082 std::optional<ui::LogicalDisplayId> expectedDisplayId,
Prabir Pradhanc5340732024-03-20 22:53:52 +000083 std::optional<int32_t> expectedFlags);
84
85 std::unique_ptr<MotionEvent> consumeMotion();
86 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher);
87
88 void consumeFocusEvent(bool hasFocus, bool inTouchMode);
89 void consumeCaptureEvent(bool hasCapture);
90 void consumeDragEvent(bool isExiting, float x, float y);
91 void consumeTouchModeEvent(bool inTouchMode);
92
93 void assertNoEvents(std::chrono::milliseconds timeout);
94
95 sp<IBinder> getToken();
96 int getChannelFd();
97
98private:
99 InputConsumer mConsumer;
100 DynamicInputEventFactory mEventFactory;
101 std::string mName;
102};
103
104// --- FakeWindowHandle ---
105
106class FakeWindowHandle : public gui::WindowInfoHandle {
107public:
108 static const int32_t WIDTH = 600;
109 static const int32_t HEIGHT = 800;
110 using InputConfig = gui::WindowInfo::InputConfig;
111
112 // This is a callback that is fired when an event is received by the window.
113 // It is static to avoid having to pass it individually into all of the FakeWindowHandles
114 // created by tests.
115 // TODO(b/210460522): Update the tests to use a factory pattern so that we can avoid
116 // the need to make this static.
117 static std::function<void(const std::unique_ptr<InputEvent>&, const gui::WindowInfo&)>
118 sOnEventReceivedCallback;
119
120 FakeWindowHandle(const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
121 const std::unique_ptr<inputdispatcher::InputDispatcher>& dispatcher,
Linnan Li13bf76a2024-05-05 19:18:02 +0800122 const std::string name, ui::LogicalDisplayId displayId,
123 bool createInputChannel = true);
Prabir Pradhanc5340732024-03-20 22:53:52 +0000124
Linnan Li13bf76a2024-05-05 19:18:02 +0800125 sp<FakeWindowHandle> clone(ui::LogicalDisplayId displayId);
Prabir Pradhanc5340732024-03-20 22:53:52 +0000126
127 inline void setTouchable(bool touchable) {
128 mInfo.setInputConfig(InputConfig::NOT_TOUCHABLE, !touchable);
129 }
130
131 inline void setFocusable(bool focusable) {
132 mInfo.setInputConfig(InputConfig::NOT_FOCUSABLE, !focusable);
133 }
134
135 inline void setVisible(bool visible) {
136 mInfo.setInputConfig(InputConfig::NOT_VISIBLE, !visible);
137 }
138
139 inline void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
140 mInfo.dispatchingTimeout = timeout;
141 }
142
143 inline void setPaused(bool paused) {
144 mInfo.setInputConfig(InputConfig::PAUSE_DISPATCHING, paused);
145 }
146
147 inline void setPreventSplitting(bool preventSplitting) {
148 mInfo.setInputConfig(InputConfig::PREVENT_SPLITTING, preventSplitting);
149 }
150
151 inline void setSlippery(bool slippery) {
152 mInfo.setInputConfig(InputConfig::SLIPPERY, slippery);
153 }
154
155 inline void setWatchOutsideTouch(bool watchOutside) {
156 mInfo.setInputConfig(InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
157 }
158
159 inline void setSpy(bool spy) { mInfo.setInputConfig(InputConfig::SPY, spy); }
160
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000161 inline void setSecure(bool secure) {
162 if (secure) {
163 mInfo.layoutParamsFlags |= gui::WindowInfo::Flag::SECURE;
164 } else {
165 using namespace ftl::flag_operators;
166 mInfo.layoutParamsFlags &= ~gui::WindowInfo::Flag::SECURE;
167 }
Arpit Singh490ccc92024-04-30 14:26:21 +0000168 mInfo.setInputConfig(InputConfig::SENSITIVE_FOR_PRIVACY, secure);
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000169 }
170
Prabir Pradhanc5340732024-03-20 22:53:52 +0000171 inline void setInterceptsStylus(bool interceptsStylus) {
172 mInfo.setInputConfig(InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
173 }
174
175 inline void setDropInput(bool dropInput) {
176 mInfo.setInputConfig(InputConfig::DROP_INPUT, dropInput);
177 }
178
179 inline void setDropInputIfObscured(bool dropInputIfObscured) {
180 mInfo.setInputConfig(InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
181 }
182
183 inline void setNoInputChannel(bool noInputChannel) {
184 mInfo.setInputConfig(InputConfig::NO_INPUT_CHANNEL, noInputChannel);
185 }
186
187 inline void setDisableUserActivity(bool disableUserActivity) {
188 mInfo.setInputConfig(InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
189 }
190
191 inline void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
192 mInfo.setInputConfig(InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH, shouldGlobalStylusBlockTouch);
193 }
194
195 inline void setAlpha(float alpha) { mInfo.alpha = alpha; }
196
197 inline void setTouchOcclusionMode(gui::TouchOcclusionMode mode) {
198 mInfo.touchOcclusionMode = mode;
199 }
200
201 inline void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
202
203 inline void setFrame(const Rect& frame,
204 const ui::Transform& displayTransform = ui::Transform()) {
205 mInfo.frame = frame;
206 mInfo.touchableRegion.clear();
207 mInfo.addTouchableRegion(frame);
208
209 const Rect logicalDisplayFrame = displayTransform.transform(frame);
210 ui::Transform translate;
211 translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
212 mInfo.transform = translate * displayTransform;
213 }
214
215 inline void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
216
217 inline void setIsWallpaper(bool isWallpaper) {
218 mInfo.setInputConfig(InputConfig::IS_WALLPAPER, isWallpaper);
219 }
220
221 inline void setDupTouchToWallpaper(bool hasWallpaper) {
222 mInfo.setInputConfig(InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
223 }
224
225 inline void setTrustedOverlay(bool trustedOverlay) {
226 mInfo.setInputConfig(InputConfig::TRUSTED_OVERLAY, trustedOverlay);
227 }
228
229 inline void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
230 mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
231 }
232
233 inline void setWindowScale(float xScale, float yScale) {
234 setWindowTransform(xScale, 0, 0, yScale);
235 }
236
237 inline void setWindowOffset(float offsetX, float offsetY) {
238 mInfo.transform.set(offsetX, offsetY);
239 }
240
241 std::unique_ptr<KeyEvent> consumeKey(bool handled = true);
242
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000243 inline std::unique_ptr<KeyEvent> consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000244 std::unique_ptr<KeyEvent> keyEvent = consumeKey();
Prabir Pradhan9a9897d2024-03-21 21:52:57 +0000245 EXPECT_NE(nullptr, keyEvent);
246 if (!keyEvent) {
247 return nullptr;
248 }
249 EXPECT_THAT(*keyEvent, matcher);
250 return keyEvent;
Prabir Pradhanc5340732024-03-20 22:53:52 +0000251 }
252
Linnan Li13bf76a2024-05-05 19:18:02 +0800253 inline void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000254 consumeKeyEvent(testing::AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
255 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
256 }
257
Linnan Li13bf76a2024-05-05 19:18:02 +0800258 inline void consumeKeyUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000259 consumeKeyEvent(testing::AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
260 WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
261 }
262
Linnan Li13bf76a2024-05-05 19:18:02 +0800263 inline void consumeMotionCancel(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700264 ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
Linnan Li13bf76a2024-05-05 19:18:02 +0800265 int32_t expectedFlags = 0) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000266 consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
267 WithDisplayId(expectedDisplayId),
268 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
269 }
270
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700271 inline void consumeMotionMove(
272 ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
273 int32_t expectedFlags = 0) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000274 consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
275 WithDisplayId(expectedDisplayId),
276 WithFlags(expectedFlags)));
277 }
278
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700279 inline void consumeMotionDown(
280 ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
281 int32_t expectedFlags = 0) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000282 consumeAnyMotionDown(expectedDisplayId, expectedFlags);
283 }
284
Linnan Li13bf76a2024-05-05 19:18:02 +0800285 inline void consumeAnyMotionDown(
286 std::optional<ui::LogicalDisplayId> expectedDisplayId = std::nullopt,
287 std::optional<int32_t> expectedFlags = std::nullopt) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000288 consumeMotionEvent(
289 testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
290 testing::Conditional(expectedDisplayId.has_value(),
291 WithDisplayId(*expectedDisplayId), testing::_),
292 testing::Conditional(expectedFlags.has_value(),
293 WithFlags(*expectedFlags), testing::_)));
294 }
295
Linnan Li13bf76a2024-05-05 19:18:02 +0800296 inline void consumeMotionPointerDown(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700297 int32_t pointerIdx,
298 ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
Linnan Li13bf76a2024-05-05 19:18:02 +0800299 int32_t expectedFlags = 0) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000300 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
301 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
302 consumeMotionEvent(testing::AllOf(WithMotionAction(action),
303 WithDisplayId(expectedDisplayId),
304 WithFlags(expectedFlags)));
305 }
306
Siarhei Vishniakouac42d242024-06-28 10:43:53 -0700307 inline void consumeMotionPointerDown(int32_t pointerIdx,
308 const ::testing::Matcher<MotionEvent>& matcher) {
309 const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
310 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
311 consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher));
312 }
313
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +0000314 inline void consumeMotionPointerUp(int32_t pointerIdx,
315 const ::testing::Matcher<MotionEvent>& matcher) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000316 const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
317 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +0000318 consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher));
Prabir Pradhanc5340732024-03-20 22:53:52 +0000319 }
320
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700321 inline void consumeMotionUp(
322 ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
323 int32_t expectedFlags = 0) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000324 consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
325 WithDisplayId(expectedDisplayId),
326 WithFlags(expectedFlags)));
327 }
328
Linnan Li13bf76a2024-05-05 19:18:02 +0800329 inline void consumeMotionOutside(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700330 ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
Linnan Li13bf76a2024-05-05 19:18:02 +0800331 int32_t expectedFlags = 0) {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000332 consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
333 WithDisplayId(expectedDisplayId),
334 WithFlags(expectedFlags)));
335 }
336
337 inline void consumeMotionOutsideWithZeroedCoords() {
338 consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
339 WithRawCoords(0, 0)));
340 }
341
342 inline void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
343 ASSERT_NE(mInputReceiver, nullptr)
344 << "Cannot consume events from a window with no receiver";
345 mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
346 }
347
348 inline void consumeCaptureEvent(bool hasCapture) {
349 ASSERT_NE(mInputReceiver, nullptr)
350 << "Cannot consume events from a window with no receiver";
351 mInputReceiver->consumeCaptureEvent(hasCapture);
352 }
353
354 std::unique_ptr<MotionEvent> consumeMotionEvent(
355 const ::testing::Matcher<MotionEvent>& matcher = testing::_);
356
357 inline void consumeDragEvent(bool isExiting, float x, float y) {
358 mInputReceiver->consumeDragEvent(isExiting, x, y);
359 }
360
361 inline void consumeTouchModeEvent(bool inTouchMode) {
362 ASSERT_NE(mInputReceiver, nullptr)
363 << "Cannot consume events from a window with no receiver";
364 mInputReceiver->consumeTouchModeEvent(inTouchMode);
365 }
366
367 inline std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
368 return receive();
369 }
370
371 inline void finishEvent(uint32_t sequenceNum) {
372 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
373 mInputReceiver->finishEvent(sequenceNum);
374 }
375
376 inline void sendTimeline(int32_t inputEventId,
377 std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
378 ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
379 mInputReceiver->sendTimeline(inputEventId, timeline);
380 }
381
382 void assertNoEvents(std::optional<std::chrono::milliseconds> timeout = {});
383
384 inline sp<IBinder> getToken() { return mInfo.token; }
385
386 inline const std::string& getName() { return mName; }
387
388 inline void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
389 mInfo.ownerPid = ownerPid;
390 mInfo.ownerUid = ownerUid;
391 }
392
393 inline gui::Pid getPid() const { return mInfo.ownerPid; }
394
395 inline void destroyReceiver() { mInputReceiver = nullptr; }
396
397 inline int getChannelFd() { return mInputReceiver->getChannelFd(); }
398
399 // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
400 std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true);
401
402private:
403 FakeWindowHandle(std::string name) : mName(name){};
404 const std::string mName;
405 std::shared_ptr<FakeInputReceiver> mInputReceiver;
406 static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
407 friend class sp<FakeWindowHandle>;
408
409 // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
410 std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive();
411};
412
413} // namespace android