1 /*
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 "FakeWindows.h"
18
19 #include <gtest/gtest.h>
20
21 namespace android {
22
23 // --- FakeInputReceiver ---
24
FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel,const std::string name)25 FakeInputReceiver::FakeInputReceiver(std::unique_ptr<InputChannel> clientChannel,
26 const std::string name)
27 : mConsumer(std::move(clientChannel)), mName(name) {}
28
consume(std::chrono::milliseconds timeout,bool handled)29 std::unique_ptr<InputEvent> FakeInputReceiver::consume(std::chrono::milliseconds timeout,
30 bool handled) {
31 auto [consumeSeq, event] = receiveEvent(timeout);
32 if (!consumeSeq) {
33 return nullptr;
34 }
35 finishEvent(*consumeSeq, handled);
36 return std::move(event);
37 }
38
receiveEvent(std::chrono::milliseconds timeout)39 std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> FakeInputReceiver::receiveEvent(
40 std::chrono::milliseconds timeout) {
41 uint32_t consumeSeq;
42 std::unique_ptr<InputEvent> event;
43
44 std::chrono::time_point start = std::chrono::steady_clock::now();
45 status_t status = WOULD_BLOCK;
46 while (status == WOULD_BLOCK) {
47 InputEvent* rawEventPtr = nullptr;
48 status = mConsumer.consume(&mEventFactory, /*consumeBatches=*/true, -1, &consumeSeq,
49 &rawEventPtr);
50 event = std::unique_ptr<InputEvent>(rawEventPtr);
51 std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
52 if (elapsed > timeout) {
53 break;
54 }
55 }
56
57 if (status == WOULD_BLOCK) {
58 // Just means there's no event available.
59 return std::make_pair(std::nullopt, nullptr);
60 }
61
62 if (status != OK) {
63 ADD_FAILURE() << mName.c_str() << ": consumer consume should return OK.";
64 return std::make_pair(std::nullopt, nullptr);
65 }
66 if (event == nullptr) {
67 ADD_FAILURE() << "Consumed correctly, but received NULL event from consumer";
68 }
69 return std::make_pair(consumeSeq, std::move(event));
70 }
71
finishEvent(uint32_t consumeSeq,bool handled)72 void FakeInputReceiver::finishEvent(uint32_t consumeSeq, bool handled) {
73 const status_t status = mConsumer.sendFinishedSignal(consumeSeq, handled);
74 ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
75 }
76
sendTimeline(int32_t inputEventId,std::array<nsecs_t,GraphicsTimeline::SIZE> timeline)77 void FakeInputReceiver::sendTimeline(int32_t inputEventId,
78 std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
79 const status_t status = mConsumer.sendTimeline(inputEventId, timeline);
80 ASSERT_EQ(OK, status);
81 }
82
consumeEvent(InputEventType expectedEventType,int32_t expectedAction,std::optional<ui::LogicalDisplayId> expectedDisplayId,std::optional<int32_t> expectedFlags)83 void FakeInputReceiver::consumeEvent(InputEventType expectedEventType, int32_t expectedAction,
84 std::optional<ui::LogicalDisplayId> expectedDisplayId,
85 std::optional<int32_t> expectedFlags) {
86 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
87
88 ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event.";
89 ASSERT_EQ(expectedEventType, event->getType())
90 << mName.c_str() << " expected " << ftl::enum_string(expectedEventType)
91 << " event, got " << *event;
92
93 if (expectedDisplayId.has_value()) {
94 EXPECT_EQ(expectedDisplayId, event->getDisplayId());
95 }
96
97 switch (expectedEventType) {
98 case InputEventType::KEY: {
99 const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
100 ASSERT_THAT(keyEvent, WithKeyAction(expectedAction));
101 if (expectedFlags.has_value()) {
102 EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
103 }
104 break;
105 }
106 case InputEventType::MOTION: {
107 const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
108 ASSERT_THAT(motionEvent, WithMotionAction(expectedAction));
109 if (expectedFlags.has_value()) {
110 EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
111 }
112 break;
113 }
114 case InputEventType::FOCUS: {
115 FAIL() << "Use 'consumeFocusEvent' for FOCUS events";
116 }
117 case InputEventType::CAPTURE: {
118 FAIL() << "Use 'consumeCaptureEvent' for CAPTURE events";
119 }
120 case InputEventType::TOUCH_MODE: {
121 FAIL() << "Use 'consumeTouchModeEvent' for TOUCH_MODE events";
122 }
123 case InputEventType::DRAG: {
124 FAIL() << "Use 'consumeDragEvent' for DRAG events";
125 }
126 }
127 }
128
consumeMotion()129 std::unique_ptr<MotionEvent> FakeInputReceiver::consumeMotion() {
130 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
131
132 if (event == nullptr) {
133 ADD_FAILURE() << mName << ": expected a MotionEvent, but didn't get one.";
134 return nullptr;
135 }
136
137 if (event->getType() != InputEventType::MOTION) {
138 ADD_FAILURE() << mName << " expected a MotionEvent, got " << *event;
139 return nullptr;
140 }
141 return std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
142 }
143
consumeMotionEvent(const::testing::Matcher<MotionEvent> & matcher)144 void FakeInputReceiver::consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
145 std::unique_ptr<MotionEvent> motionEvent = consumeMotion();
146 ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
147 ASSERT_THAT(*motionEvent, matcher);
148 }
149
consumeFocusEvent(bool hasFocus,bool inTouchMode)150 void FakeInputReceiver::consumeFocusEvent(bool hasFocus, bool inTouchMode) {
151 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
152 ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event.";
153 ASSERT_EQ(InputEventType::FOCUS, event->getType()) << "Instead of FocusEvent, got " << *event;
154
155 ASSERT_EQ(ui::LogicalDisplayId::INVALID, event->getDisplayId())
156 << mName.c_str() << ": event displayId should always be NONE.";
157
158 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
159 EXPECT_EQ(hasFocus, focusEvent.getHasFocus());
160 }
161
consumeCaptureEvent(bool hasCapture)162 void FakeInputReceiver::consumeCaptureEvent(bool hasCapture) {
163 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
164 ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event.";
165 ASSERT_EQ(InputEventType::CAPTURE, event->getType())
166 << "Instead of CaptureEvent, got " << *event;
167
168 ASSERT_EQ(ui::LogicalDisplayId::INVALID, event->getDisplayId())
169 << mName.c_str() << ": event displayId should always be NONE.";
170
171 const auto& captureEvent = static_cast<const CaptureEvent&>(*event);
172 EXPECT_EQ(hasCapture, captureEvent.getPointerCaptureEnabled());
173 }
174
consumeDragEvent(bool isExiting,float x,float y)175 void FakeInputReceiver::consumeDragEvent(bool isExiting, float x, float y) {
176 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
177 ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event.";
178 ASSERT_EQ(InputEventType::DRAG, event->getType()) << "Instead of DragEvent, got " << *event;
179
180 EXPECT_EQ(ui::LogicalDisplayId::INVALID, event->getDisplayId())
181 << mName.c_str() << ": event displayId should always be NONE.";
182
183 const auto& dragEvent = static_cast<const DragEvent&>(*event);
184 EXPECT_EQ(isExiting, dragEvent.isExiting());
185 EXPECT_EQ(x, dragEvent.getX());
186 EXPECT_EQ(y, dragEvent.getY());
187 }
188
consumeTouchModeEvent(bool inTouchMode)189 void FakeInputReceiver::consumeTouchModeEvent(bool inTouchMode) {
190 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
191 ASSERT_NE(nullptr, event) << mName.c_str() << ": consumer should have returned non-NULL event.";
192 ASSERT_EQ(InputEventType::TOUCH_MODE, event->getType())
193 << "Instead of TouchModeEvent, got " << *event;
194
195 ASSERT_EQ(ui::LogicalDisplayId::INVALID, event->getDisplayId())
196 << mName.c_str() << ": event displayId should always be NONE.";
197 const auto& touchModeEvent = static_cast<const TouchModeEvent&>(*event);
198 EXPECT_EQ(inTouchMode, touchModeEvent.isInTouchMode());
199 }
200
assertNoEvents(std::chrono::milliseconds timeout)201 void FakeInputReceiver::assertNoEvents(std::chrono::milliseconds timeout) {
202 std::unique_ptr<InputEvent> event = consume(timeout);
203 if (event == nullptr) {
204 return;
205 }
206 if (event->getType() == InputEventType::KEY) {
207 KeyEvent& keyEvent = static_cast<KeyEvent&>(*event);
208 ADD_FAILURE() << "Received key event " << keyEvent;
209 } else if (event->getType() == InputEventType::MOTION) {
210 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
211 ADD_FAILURE() << "Received motion event " << motionEvent;
212 } else if (event->getType() == InputEventType::FOCUS) {
213 FocusEvent& focusEvent = static_cast<FocusEvent&>(*event);
214 ADD_FAILURE() << "Received focus event, hasFocus = "
215 << (focusEvent.getHasFocus() ? "true" : "false");
216 } else if (event->getType() == InputEventType::CAPTURE) {
217 const auto& captureEvent = static_cast<CaptureEvent&>(*event);
218 ADD_FAILURE() << "Received capture event, pointerCaptureEnabled = "
219 << (captureEvent.getPointerCaptureEnabled() ? "true" : "false");
220 } else if (event->getType() == InputEventType::TOUCH_MODE) {
221 const auto& touchModeEvent = static_cast<TouchModeEvent&>(*event);
222 ADD_FAILURE() << "Received touch mode event, inTouchMode = "
223 << (touchModeEvent.isInTouchMode() ? "true" : "false");
224 }
225 FAIL() << mName.c_str()
226 << ": should not have received any events, so consume() should return NULL";
227 }
228
getToken()229 sp<IBinder> FakeInputReceiver::getToken() {
230 return mConsumer.getChannel()->getConnectionToken();
231 }
232
getChannelFd()233 int FakeInputReceiver::getChannelFd() {
234 return mConsumer.getChannel()->getFd();
235 }
236
237 // --- FakeWindowHandle ---
238
239 std::function<void(const std::unique_ptr<InputEvent>&, const gui::WindowInfo&)>
240 FakeWindowHandle::sOnEventReceivedCallback{};
241
242 std::atomic<int32_t> FakeWindowHandle::sId{1};
243
FakeWindowHandle(const std::shared_ptr<InputApplicationHandle> & inputApplicationHandle,const std::unique_ptr<inputdispatcher::InputDispatcher> & dispatcher,const std::string name,ui::LogicalDisplayId displayId,bool createInputChannel)244 FakeWindowHandle::FakeWindowHandle(
245 const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
246 const std::unique_ptr<inputdispatcher::InputDispatcher>& dispatcher, const std::string name,
247 ui::LogicalDisplayId displayId, bool createInputChannel)
248 : mName(name) {
249 sp<IBinder> token;
250 if (createInputChannel) {
251 base::Result<std::unique_ptr<InputChannel>> channel = dispatcher->createInputChannel(name);
252 token = (*channel)->getConnectionToken();
253 mInputReceiver = std::make_unique<FakeInputReceiver>(std::move(*channel), name);
254 }
255
256 inputApplicationHandle->updateInfo();
257 mInfo.applicationInfo = *inputApplicationHandle->getInfo();
258
259 mInfo.token = token;
260 mInfo.id = sId++;
261 mInfo.name = name;
262 mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
263 mInfo.alpha = 1.0;
264 mInfo.frame = Rect(0, 0, WIDTH, HEIGHT);
265 mInfo.transform.set(0, 0);
266 mInfo.globalScaleFactor = 1.0;
267 mInfo.touchableRegion.clear();
268 mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
269 mInfo.ownerPid = WINDOW_PID;
270 mInfo.ownerUid = WINDOW_UID;
271 mInfo.displayId = displayId;
272 mInfo.inputConfig = InputConfig::DEFAULT;
273 }
274
clone(ui::LogicalDisplayId displayId)275 sp<FakeWindowHandle> FakeWindowHandle::clone(ui::LogicalDisplayId displayId) {
276 sp<FakeWindowHandle> handle = sp<FakeWindowHandle>::make(mInfo.name + "(Mirror)");
277 handle->mInfo = mInfo;
278 handle->mInfo.displayId = displayId;
279 handle->mInfo.id = sId++;
280 handle->mInputReceiver = mInputReceiver;
281 return handle;
282 }
283
consumeKey(bool handled)284 std::unique_ptr<KeyEvent> FakeWindowHandle::consumeKey(bool handled) {
285 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED, handled);
286 if (event == nullptr) {
287 ADD_FAILURE() << "No event";
288 return nullptr;
289 }
290 if (event->getType() != InputEventType::KEY) {
291 ADD_FAILURE() << "Instead of key event, got " << event;
292 return nullptr;
293 }
294 return std::unique_ptr<KeyEvent>(static_cast<KeyEvent*>(event.release()));
295 }
296
consumeMotionEvent(const::testing::Matcher<MotionEvent> & matcher)297 std::unique_ptr<MotionEvent> FakeWindowHandle::consumeMotionEvent(
298 const ::testing::Matcher<MotionEvent>& matcher) {
299 std::unique_ptr<InputEvent> event = consume(CONSUME_TIMEOUT_EVENT_EXPECTED);
300 if (event == nullptr) {
301 std::ostringstream matcherDescription;
302 matcher.DescribeTo(&matcherDescription);
303 ADD_FAILURE() << "No event (expected " << matcherDescription.str() << ") on " << mName;
304 return nullptr;
305 }
306 if (event->getType() != InputEventType::MOTION) {
307 ADD_FAILURE() << "Instead of motion event, got " << *event << " on " << mName;
308 return nullptr;
309 }
310 std::unique_ptr<MotionEvent> motionEvent =
311 std::unique_ptr<MotionEvent>(static_cast<MotionEvent*>(event.release()));
312 if (motionEvent == nullptr) {
313 return nullptr;
314 }
315 EXPECT_THAT(*motionEvent, matcher) << " on " << mName;
316 return motionEvent;
317 }
318
assertNoEvents(std::optional<std::chrono::milliseconds> timeout)319 void FakeWindowHandle::assertNoEvents(std::optional<std::chrono::milliseconds> timeout) {
320 if (mInputReceiver == nullptr && mInfo.inputConfig.test(InputConfig::NO_INPUT_CHANNEL)) {
321 return; // Can't receive events if the window does not have input channel
322 }
323 ASSERT_NE(nullptr, mInputReceiver)
324 << "Window without InputReceiver must specify feature NO_INPUT_CHANNEL";
325 mInputReceiver->assertNoEvents(timeout.value_or(CONSUME_TIMEOUT_NO_EVENT_EXPECTED));
326 }
327
consume(std::chrono::milliseconds timeout,bool handled)328 std::unique_ptr<InputEvent> FakeWindowHandle::consume(std::chrono::milliseconds timeout,
329 bool handled) {
330 if (mInputReceiver == nullptr) {
331 LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
332 }
333 std::unique_ptr<InputEvent> event = mInputReceiver->consume(timeout, handled);
334 if (event == nullptr) {
335 ADD_FAILURE() << "Consume failed: no event";
336 }
337
338 if (sOnEventReceivedCallback != nullptr) {
339 sOnEventReceivedCallback(event, mInfo);
340 }
341 return event;
342 }
343
344 std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>>
receive()345 FakeWindowHandle::receive() {
346 if (mInputReceiver == nullptr) {
347 ADD_FAILURE() << "Invalid receive event on window with no receiver";
348 return std::make_pair(std::nullopt, nullptr);
349 }
350 auto out = mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
351 const auto& [_, event] = out;
352
353 if (sOnEventReceivedCallback != nullptr) {
354 sOnEventReceivedCallback(event, mInfo);
355 }
356 return out;
357 }
358
359 } // namespace android
360