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