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