• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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 
27 namespace 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  */
36 static 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  */
45 static 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  */
50 static constexpr gui::Pid WINDOW_PID{999};
51 static 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  */
57 static 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 
63 class FakeInputReceiver {
64 public:
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,
82                       std::optional<ui::LogicalDisplayId> expectedDisplayId,
83                       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 
98 private:
99     InputConsumer mConsumer;
100     DynamicInputEventFactory mEventFactory;
101     std::string mName;
102 };
103 
104 // --- FakeWindowHandle ---
105 
106 class FakeWindowHandle : public gui::WindowInfoHandle {
107 public:
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,
122                      const std::string name, ui::LogicalDisplayId displayId,
123                      bool createInputChannel = true);
124 
125     sp<FakeWindowHandle> clone(ui::LogicalDisplayId displayId);
126 
setTouchable(bool touchable)127     inline void setTouchable(bool touchable) {
128         mInfo.setInputConfig(InputConfig::NOT_TOUCHABLE, !touchable);
129     }
130 
setFocusable(bool focusable)131     inline void setFocusable(bool focusable) {
132         mInfo.setInputConfig(InputConfig::NOT_FOCUSABLE, !focusable);
133     }
134 
setVisible(bool visible)135     inline void setVisible(bool visible) {
136         mInfo.setInputConfig(InputConfig::NOT_VISIBLE, !visible);
137     }
138 
setDispatchingTimeout(std::chrono::nanoseconds timeout)139     inline void setDispatchingTimeout(std::chrono::nanoseconds timeout) {
140         mInfo.dispatchingTimeout = timeout;
141     }
142 
setPaused(bool paused)143     inline void setPaused(bool paused) {
144         mInfo.setInputConfig(InputConfig::PAUSE_DISPATCHING, paused);
145     }
146 
setPreventSplitting(bool preventSplitting)147     inline void setPreventSplitting(bool preventSplitting) {
148         mInfo.setInputConfig(InputConfig::PREVENT_SPLITTING, preventSplitting);
149     }
150 
setSlippery(bool slippery)151     inline void setSlippery(bool slippery) {
152         mInfo.setInputConfig(InputConfig::SLIPPERY, slippery);
153     }
154 
setWatchOutsideTouch(bool watchOutside)155     inline void setWatchOutsideTouch(bool watchOutside) {
156         mInfo.setInputConfig(InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
157     }
158 
setSpy(bool spy)159     inline void setSpy(bool spy) { mInfo.setInputConfig(InputConfig::SPY, spy); }
160 
setSecure(bool secure)161     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         }
168         mInfo.setInputConfig(InputConfig::SENSITIVE_FOR_PRIVACY, secure);
169     }
170 
setInterceptsStylus(bool interceptsStylus)171     inline void setInterceptsStylus(bool interceptsStylus) {
172         mInfo.setInputConfig(InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
173     }
174 
setDropInput(bool dropInput)175     inline void setDropInput(bool dropInput) {
176         mInfo.setInputConfig(InputConfig::DROP_INPUT, dropInput);
177     }
178 
setDropInputIfObscured(bool dropInputIfObscured)179     inline void setDropInputIfObscured(bool dropInputIfObscured) {
180         mInfo.setInputConfig(InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
181     }
182 
setNoInputChannel(bool noInputChannel)183     inline void setNoInputChannel(bool noInputChannel) {
184         mInfo.setInputConfig(InputConfig::NO_INPUT_CHANNEL, noInputChannel);
185     }
186 
setDisableUserActivity(bool disableUserActivity)187     inline void setDisableUserActivity(bool disableUserActivity) {
188         mInfo.setInputConfig(InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
189     }
190 
setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch)191     inline void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
192         mInfo.setInputConfig(InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH, shouldGlobalStylusBlockTouch);
193     }
194 
setAlpha(float alpha)195     inline void setAlpha(float alpha) { mInfo.alpha = alpha; }
196 
setTouchOcclusionMode(gui::TouchOcclusionMode mode)197     inline void setTouchOcclusionMode(gui::TouchOcclusionMode mode) {
198         mInfo.touchOcclusionMode = mode;
199     }
200 
setApplicationToken(sp<IBinder> token)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 
setTouchableRegion(const Region & region)215     inline void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
216 
setIsWallpaper(bool isWallpaper)217     inline void setIsWallpaper(bool isWallpaper) {
218         mInfo.setInputConfig(InputConfig::IS_WALLPAPER, isWallpaper);
219     }
220 
setDupTouchToWallpaper(bool hasWallpaper)221     inline void setDupTouchToWallpaper(bool hasWallpaper) {
222         mInfo.setInputConfig(InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
223     }
224 
setTrustedOverlay(bool trustedOverlay)225     inline void setTrustedOverlay(bool trustedOverlay) {
226         mInfo.setInputConfig(InputConfig::TRUSTED_OVERLAY, trustedOverlay);
227     }
228 
setWindowTransform(float dsdx,float dtdx,float dtdy,float dsdy)229     inline void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
230         mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
231     }
232 
setWindowScale(float xScale,float yScale)233     inline void setWindowScale(float xScale, float yScale) {
234         setWindowTransform(xScale, 0, 0, yScale);
235     }
236 
setWindowOffset(float offsetX,float offsetY)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 
consumeKeyEvent(const::testing::Matcher<KeyEvent> & matcher)243     inline std::unique_ptr<KeyEvent> consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
244         std::unique_ptr<KeyEvent> keyEvent = consumeKey();
245         EXPECT_NE(nullptr, keyEvent);
246         if (!keyEvent) {
247             return nullptr;
248         }
249         EXPECT_THAT(*keyEvent, matcher);
250         return keyEvent;
251     }
252 
253     inline void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
254         consumeKeyEvent(testing::AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
255                                        WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
256     }
257 
258     inline void consumeKeyUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
259         consumeKeyEvent(testing::AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
260                                        WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
261     }
262 
263     inline void consumeMotionCancel(
264             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
265             int32_t expectedFlags = 0) {
266         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
267                                           WithDisplayId(expectedDisplayId),
268                                           WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
269     }
270 
271     inline void consumeMotionMove(
272             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
273             int32_t expectedFlags = 0) {
274         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
275                                           WithDisplayId(expectedDisplayId),
276                                           WithFlags(expectedFlags)));
277     }
278 
279     inline void consumeMotionDown(
280             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
281             int32_t expectedFlags = 0) {
282         consumeAnyMotionDown(expectedDisplayId, expectedFlags);
283     }
284 
285     inline void consumeAnyMotionDown(
286             std::optional<ui::LogicalDisplayId> expectedDisplayId = std::nullopt,
287             std::optional<int32_t> expectedFlags = std::nullopt) {
288         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 
296     inline void consumeMotionPointerDown(
297             int32_t pointerIdx,
298             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
299             int32_t expectedFlags = 0) {
300         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 
consumeMotionPointerUp(int32_t pointerIdx,const::testing::Matcher<MotionEvent> & matcher)307     inline void consumeMotionPointerUp(int32_t pointerIdx,
308                                        const ::testing::Matcher<MotionEvent>& matcher) {
309         const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
310                 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
311         consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher));
312     }
313 
314     inline void consumeMotionUp(
315             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
316             int32_t expectedFlags = 0) {
317         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
318                                           WithDisplayId(expectedDisplayId),
319                                           WithFlags(expectedFlags)));
320     }
321 
322     inline void consumeMotionOutside(
323             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
324             int32_t expectedFlags = 0) {
325         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
326                                           WithDisplayId(expectedDisplayId),
327                                           WithFlags(expectedFlags)));
328     }
329 
consumeMotionOutsideWithZeroedCoords()330     inline void consumeMotionOutsideWithZeroedCoords() {
331         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
332                                           WithRawCoords(0, 0)));
333     }
334 
335     inline void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
336         ASSERT_NE(mInputReceiver, nullptr)
337                 << "Cannot consume events from a window with no receiver";
338         mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
339     }
340 
consumeCaptureEvent(bool hasCapture)341     inline void consumeCaptureEvent(bool hasCapture) {
342         ASSERT_NE(mInputReceiver, nullptr)
343                 << "Cannot consume events from a window with no receiver";
344         mInputReceiver->consumeCaptureEvent(hasCapture);
345     }
346 
347     std::unique_ptr<MotionEvent> consumeMotionEvent(
348             const ::testing::Matcher<MotionEvent>& matcher = testing::_);
349 
consumeDragEvent(bool isExiting,float x,float y)350     inline void consumeDragEvent(bool isExiting, float x, float y) {
351         mInputReceiver->consumeDragEvent(isExiting, x, y);
352     }
353 
consumeTouchModeEvent(bool inTouchMode)354     inline void consumeTouchModeEvent(bool inTouchMode) {
355         ASSERT_NE(mInputReceiver, nullptr)
356                 << "Cannot consume events from a window with no receiver";
357         mInputReceiver->consumeTouchModeEvent(inTouchMode);
358     }
359 
receiveEvent()360     inline std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
361         return receive();
362     }
363 
finishEvent(uint32_t sequenceNum)364     inline void finishEvent(uint32_t sequenceNum) {
365         ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
366         mInputReceiver->finishEvent(sequenceNum);
367     }
368 
sendTimeline(int32_t inputEventId,std::array<nsecs_t,GraphicsTimeline::SIZE> timeline)369     inline void sendTimeline(int32_t inputEventId,
370                              std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
371         ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
372         mInputReceiver->sendTimeline(inputEventId, timeline);
373     }
374 
375     void assertNoEvents(std::optional<std::chrono::milliseconds> timeout = {});
376 
getToken()377     inline sp<IBinder> getToken() { return mInfo.token; }
378 
getName()379     inline const std::string& getName() { return mName; }
380 
setOwnerInfo(gui::Pid ownerPid,gui::Uid ownerUid)381     inline void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
382         mInfo.ownerPid = ownerPid;
383         mInfo.ownerUid = ownerUid;
384     }
385 
getPid()386     inline gui::Pid getPid() const { return mInfo.ownerPid; }
387 
destroyReceiver()388     inline void destroyReceiver() { mInputReceiver = nullptr; }
389 
getChannelFd()390     inline int getChannelFd() { return mInputReceiver->getChannelFd(); }
391 
392     // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
393     std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true);
394 
395 private:
FakeWindowHandle(std::string name)396     FakeWindowHandle(std::string name) : mName(name){};
397     const std::string mName;
398     std::shared_ptr<FakeInputReceiver> mInputReceiver;
399     static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
400     friend class sp<FakeWindowHandle>;
401 
402     // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
403     std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive();
404 };
405 
406 } // namespace android
407