• 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 
setSlippery(bool slippery)147     inline void setSlippery(bool slippery) {
148         mInfo.setInputConfig(InputConfig::SLIPPERY, slippery);
149     }
150 
setWatchOutsideTouch(bool watchOutside)151     inline void setWatchOutsideTouch(bool watchOutside) {
152         mInfo.setInputConfig(InputConfig::WATCH_OUTSIDE_TOUCH, watchOutside);
153     }
154 
setSpy(bool spy)155     inline void setSpy(bool spy) { mInfo.setInputConfig(InputConfig::SPY, spy); }
156 
setSecure(bool secure)157     inline void setSecure(bool secure) {
158         if (secure) {
159             mInfo.layoutParamsFlags |= gui::WindowInfo::Flag::SECURE;
160         } else {
161             using namespace ftl::flag_operators;
162             mInfo.layoutParamsFlags &= ~gui::WindowInfo::Flag::SECURE;
163         }
164         mInfo.setInputConfig(InputConfig::SENSITIVE_FOR_PRIVACY, secure);
165     }
166 
setInterceptsStylus(bool interceptsStylus)167     inline void setInterceptsStylus(bool interceptsStylus) {
168         mInfo.setInputConfig(InputConfig::INTERCEPTS_STYLUS, interceptsStylus);
169     }
170 
setDropInput(bool dropInput)171     inline void setDropInput(bool dropInput) {
172         mInfo.setInputConfig(InputConfig::DROP_INPUT, dropInput);
173     }
174 
setDropInputIfObscured(bool dropInputIfObscured)175     inline void setDropInputIfObscured(bool dropInputIfObscured) {
176         mInfo.setInputConfig(InputConfig::DROP_INPUT_IF_OBSCURED, dropInputIfObscured);
177     }
178 
setNoInputChannel(bool noInputChannel)179     inline void setNoInputChannel(bool noInputChannel) {
180         mInfo.setInputConfig(InputConfig::NO_INPUT_CHANNEL, noInputChannel);
181     }
182 
setDisableUserActivity(bool disableUserActivity)183     inline void setDisableUserActivity(bool disableUserActivity) {
184         mInfo.setInputConfig(InputConfig::DISABLE_USER_ACTIVITY, disableUserActivity);
185     }
186 
setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch)187     inline void setGlobalStylusBlocksTouch(bool shouldGlobalStylusBlockTouch) {
188         mInfo.setInputConfig(InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH, shouldGlobalStylusBlockTouch);
189     }
190 
setAlpha(float alpha)191     inline void setAlpha(float alpha) { mInfo.alpha = alpha; }
192 
setTouchOcclusionMode(gui::TouchOcclusionMode mode)193     inline void setTouchOcclusionMode(gui::TouchOcclusionMode mode) {
194         mInfo.touchOcclusionMode = mode;
195     }
196 
setApplicationToken(sp<IBinder> token)197     inline void setApplicationToken(sp<IBinder> token) { mInfo.applicationInfo.token = token; }
198 
199     inline void setFrame(const Rect& frame,
200                          const ui::Transform& displayTransform = ui::Transform()) {
201         mInfo.frame = frame;
202         mInfo.touchableRegion.clear();
203         mInfo.addTouchableRegion(frame);
204 
205         const Rect logicalDisplayFrame = displayTransform.transform(frame);
206         ui::Transform translate;
207         translate.set(-logicalDisplayFrame.left, -logicalDisplayFrame.top);
208         mInfo.transform = translate * displayTransform;
209     }
210 
setTouchableRegion(const Region & region)211     inline void setTouchableRegion(const Region& region) { mInfo.touchableRegion = region; }
212 
setIsWallpaper(bool isWallpaper)213     inline void setIsWallpaper(bool isWallpaper) {
214         mInfo.setInputConfig(InputConfig::IS_WALLPAPER, isWallpaper);
215     }
216 
setDupTouchToWallpaper(bool hasWallpaper)217     inline void setDupTouchToWallpaper(bool hasWallpaper) {
218         mInfo.setInputConfig(InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER, hasWallpaper);
219     }
220 
setTrustedOverlay(bool trustedOverlay)221     inline void setTrustedOverlay(bool trustedOverlay) {
222         mInfo.setInputConfig(InputConfig::TRUSTED_OVERLAY, trustedOverlay);
223     }
224 
setWindowTransform(float dsdx,float dtdx,float dtdy,float dsdy)225     inline void setWindowTransform(float dsdx, float dtdx, float dtdy, float dsdy) {
226         mInfo.transform.set(dsdx, dtdx, dtdy, dsdy);
227     }
228 
setWindowScale(float xScale,float yScale)229     inline void setWindowScale(float xScale, float yScale) {
230         setWindowTransform(xScale, 0, 0, yScale);
231     }
232 
setWindowOffset(float offsetX,float offsetY)233     inline void setWindowOffset(float offsetX, float offsetY) {
234         mInfo.transform.set(offsetX, offsetY);
235     }
236 
237     std::unique_ptr<KeyEvent> consumeKey(bool handled = true);
238 
consumeKeyEvent(const::testing::Matcher<KeyEvent> & matcher)239     inline std::unique_ptr<KeyEvent> consumeKeyEvent(const ::testing::Matcher<KeyEvent>& matcher) {
240         std::unique_ptr<KeyEvent> keyEvent = consumeKey();
241         EXPECT_NE(nullptr, keyEvent);
242         if (!keyEvent) {
243             return nullptr;
244         }
245         EXPECT_THAT(*keyEvent, matcher);
246         return keyEvent;
247     }
248 
249     inline void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
250         consumeKeyEvent(testing::AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
251                                        WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
252     }
253 
254     inline void consumeKeyUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
255         consumeKeyEvent(testing::AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
256                                        WithDisplayId(expectedDisplayId), WithFlags(expectedFlags)));
257     }
258 
259     inline void consumeMotionCancel(
260             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
261             int32_t expectedFlags = 0) {
262         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
263                                           WithDisplayId(expectedDisplayId),
264                                           WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
265     }
266 
267     inline void consumeMotionMove(
268             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
269             int32_t expectedFlags = 0) {
270         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
271                                           WithDisplayId(expectedDisplayId),
272                                           WithFlags(expectedFlags)));
273     }
274 
275     inline void consumeMotionDown(
276             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
277             int32_t expectedFlags = 0) {
278         consumeAnyMotionDown(expectedDisplayId, expectedFlags);
279     }
280 
281     inline void consumeAnyMotionDown(
282             std::optional<ui::LogicalDisplayId> expectedDisplayId = std::nullopt,
283             std::optional<int32_t> expectedFlags = std::nullopt) {
284         consumeMotionEvent(
285                 testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
286                                testing::Conditional(expectedDisplayId.has_value(),
287                                                     WithDisplayId(*expectedDisplayId), testing::_),
288                                testing::Conditional(expectedFlags.has_value(),
289                                                     WithFlags(*expectedFlags), testing::_)));
290     }
291 
292     inline void consumeMotionPointerDown(
293             int32_t pointerIdx,
294             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
295             int32_t expectedFlags = 0) {
296         const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
297                 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
298         consumeMotionEvent(testing::AllOf(WithMotionAction(action),
299                                           WithDisplayId(expectedDisplayId),
300                                           WithFlags(expectedFlags)));
301     }
302 
consumeMotionPointerDown(int32_t pointerIdx,const::testing::Matcher<MotionEvent> & matcher)303     inline void consumeMotionPointerDown(int32_t pointerIdx,
304                                          const ::testing::Matcher<MotionEvent>& matcher) {
305         const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
306                 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
307         consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher));
308     }
309 
consumeMotionPointerUp(int32_t pointerIdx,const::testing::Matcher<MotionEvent> & matcher)310     inline void consumeMotionPointerUp(int32_t pointerIdx,
311                                        const ::testing::Matcher<MotionEvent>& matcher) {
312         const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
313                 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
314         consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher));
315     }
316 
317     inline void consumeMotionUp(
318             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
319             int32_t expectedFlags = 0) {
320         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
321                                           WithDisplayId(expectedDisplayId),
322                                           WithFlags(expectedFlags)));
323     }
324 
325     inline void consumeMotionOutside(
326             ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
327             int32_t expectedFlags = 0) {
328         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
329                                           WithDisplayId(expectedDisplayId),
330                                           WithFlags(expectedFlags)));
331     }
332 
consumeMotionOutsideWithZeroedCoords()333     inline void consumeMotionOutsideWithZeroedCoords() {
334         consumeMotionEvent(testing::AllOf(WithMotionAction(AMOTION_EVENT_ACTION_OUTSIDE),
335                                           WithRawCoords(0, 0)));
336     }
337 
338     inline void consumeFocusEvent(bool hasFocus, bool inTouchMode = true) {
339         ASSERT_NE(mInputReceiver, nullptr)
340                 << "Cannot consume events from a window with no receiver";
341         mInputReceiver->consumeFocusEvent(hasFocus, inTouchMode);
342     }
343 
consumeCaptureEvent(bool hasCapture)344     inline void consumeCaptureEvent(bool hasCapture) {
345         ASSERT_NE(mInputReceiver, nullptr)
346                 << "Cannot consume events from a window with no receiver";
347         mInputReceiver->consumeCaptureEvent(hasCapture);
348     }
349 
350     std::unique_ptr<MotionEvent> consumeMotionEvent(
351             const ::testing::Matcher<MotionEvent>& matcher = testing::_);
352 
consumeDragEvent(bool isExiting,float x,float y)353     inline void consumeDragEvent(bool isExiting, float x, float y) {
354         mInputReceiver->consumeDragEvent(isExiting, x, y);
355     }
356 
consumeTouchModeEvent(bool inTouchMode)357     inline void consumeTouchModeEvent(bool inTouchMode) {
358         ASSERT_NE(mInputReceiver, nullptr)
359                 << "Cannot consume events from a window with no receiver";
360         mInputReceiver->consumeTouchModeEvent(inTouchMode);
361     }
362 
receiveEvent()363     inline std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
364         return receive();
365     }
366 
finishEvent(uint32_t sequenceNum)367     inline void finishEvent(uint32_t sequenceNum) {
368         ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
369         mInputReceiver->finishEvent(sequenceNum);
370     }
371 
sendTimeline(int32_t inputEventId,std::array<nsecs_t,GraphicsTimeline::SIZE> timeline)372     inline void sendTimeline(int32_t inputEventId,
373                              std::array<nsecs_t, GraphicsTimeline::SIZE> timeline) {
374         ASSERT_NE(mInputReceiver, nullptr) << "Invalid receive event on window with no receiver";
375         mInputReceiver->sendTimeline(inputEventId, timeline);
376     }
377 
378     void assertNoEvents(std::optional<std::chrono::milliseconds> timeout = {});
379 
getToken()380     inline sp<IBinder> getToken() { return mInfo.token; }
381 
getName()382     inline const std::string& getName() { return mName; }
383 
setOwnerInfo(gui::Pid ownerPid,gui::Uid ownerUid)384     inline void setOwnerInfo(gui::Pid ownerPid, gui::Uid ownerUid) {
385         mInfo.ownerPid = ownerPid;
386         mInfo.ownerUid = ownerUid;
387     }
388 
getPid()389     inline gui::Pid getPid() const { return mInfo.ownerPid; }
390 
destroyReceiver()391     inline void destroyReceiver() { mInputReceiver = nullptr; }
392 
getChannelFd()393     inline int getChannelFd() { return mInputReceiver->getChannelFd(); }
394 
395     // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
396     std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true);
397 
398 private:
FakeWindowHandle(std::string name)399     FakeWindowHandle(std::string name) : mName(name){};
400     const std::string mName;
401     std::shared_ptr<FakeInputReceiver> mInputReceiver;
402     static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
403     friend class sp<FakeWindowHandle>;
404 
405     // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
406     std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive();
407 };
408 
409 } // namespace android
410