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