Loading services/inputflinger/tests/InputDispatcher_test.cpp +136 −7 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ using android::base::StringPrintf; using android::os::InputEventInjectionResult; using android::os::InputEventInjectionSync; using android::os::TouchOcclusionMode; using namespace android::flag_operators; namespace android::inputdispatcher { Loading Loading @@ -727,8 +728,9 @@ public: ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK."; } void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId, int32_t expectedFlags) { void consumeEvent(int32_t expectedEventType, int32_t expectedAction, std::optional<int32_t> expectedDisplayId, std::optional<int32_t> expectedFlags) { InputEvent* event = consume(); ASSERT_NE(nullptr, event) << mName.c_str() Loading @@ -737,19 +739,25 @@ public: << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType) << " event, got " << inputEventTypeToString(event->getType()) << " event"; if (expectedDisplayId.has_value()) { EXPECT_EQ(expectedDisplayId, event->getDisplayId()); } switch (expectedEventType) { case AINPUT_EVENT_TYPE_KEY: { const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event); EXPECT_EQ(expectedAction, keyEvent.getAction()); EXPECT_EQ(expectedFlags, keyEvent.getFlags()); if (expectedFlags.has_value()) { EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags()); } break; } case AINPUT_EVENT_TYPE_MOTION: { const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event); EXPECT_EQ(expectedAction, motionEvent.getAction()); EXPECT_EQ(expectedFlags, motionEvent.getFlags()); if (expectedFlags.has_value()) { EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags()); } break; } case AINPUT_EVENT_TYPE_FOCUS: { Loading Loading @@ -854,6 +862,7 @@ public: mInfo.name = name; mInfo.type = InputWindowInfo::Type::APPLICATION; mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; mInfo.alpha = 1.0; mInfo.frameLeft = 0; mInfo.frameTop = 0; mInfo.frameRight = WIDTH; Loading Loading @@ -883,6 +892,12 @@ public: void setPaused(bool paused) { mInfo.paused = paused; } void setAlpha(float alpha) { mInfo.alpha = alpha; } void setTouchOcclusionMode(android::os::TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; } void setFrame(const Rect& frame) { mInfo.frameLeft = frame.left; mInfo.frameTop = frame.top; Loading Loading @@ -928,6 +943,11 @@ public: void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) { consumeAnyMotionDown(expectedDisplayId, expectedFlags); } void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt, std::optional<int32_t> expectedFlags = std::nullopt) { consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags); } Loading Loading @@ -971,8 +991,9 @@ public: mInputReceiver->consumeCaptureEvent(hasCapture); } void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId, int32_t expectedFlags) { void consumeEvent(int32_t expectedEventType, int32_t expectedAction, std::optional<int32_t> expectedDisplayId, std::optional<int32_t> expectedFlags) { ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver"; mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId, expectedFlags); Loading Loading @@ -4240,4 +4261,112 @@ TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) { mSecondWindow->consumeCaptureEvent(true); } class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest { protected: constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8; static const int32_t APP_A_UID = 10001; static const int32_t APP_B_UID = 10002; sp<FakeWindowHandle> mTouchWindow; virtual void SetUp() override { InputDispatcherTest::SetUp(); mTouchWindow = getWindow(APP_A_UID, "Touched"); mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK); mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY); } virtual void TearDown() override { InputDispatcherTest::TearDown(); mTouchWindow.clear(); } sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, os::TouchOcclusionMode mode) { sp<FakeWindowHandle> window = getWindow(uid, name); window->setFlags(InputWindowInfo::Flag::NOT_TOUCHABLE); window->setTouchOcclusionMode(mode); return window; } sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) { std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT); // Generate an arbitrary PID based on the UID window->setOwnerInfo(1777 + (uid % 10000), uid); return window; } void touch(const std::vector<PointF>& points = {PointF{100, 200}}) { NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, points); mDispatcher->notifyMotion(&args); } }; TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch(); mTouchWindow->assertNoEvents(); } TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch(); mTouchWindow->consumeAnyMotionDown(); } TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED); window->setFrame(Rect(0, 0, 50, 50)); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch({PointF{100, 100}}); mTouchWindow->consumeAnyMotionDown(); } TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_A_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch(); mTouchWindow->consumeAnyMotionDown(); } TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY); window->setAlpha(0.7); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch(); mTouchWindow->consumeAnyMotionDown(); } TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY); window->setAlpha(0.9); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch(); mTouchWindow->assertNoEvents(); } } // namespace android::inputdispatcher Loading
services/inputflinger/tests/InputDispatcher_test.cpp +136 −7 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ using android::base::StringPrintf; using android::os::InputEventInjectionResult; using android::os::InputEventInjectionSync; using android::os::TouchOcclusionMode; using namespace android::flag_operators; namespace android::inputdispatcher { Loading Loading @@ -727,8 +728,9 @@ public: ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK."; } void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId, int32_t expectedFlags) { void consumeEvent(int32_t expectedEventType, int32_t expectedAction, std::optional<int32_t> expectedDisplayId, std::optional<int32_t> expectedFlags) { InputEvent* event = consume(); ASSERT_NE(nullptr, event) << mName.c_str() Loading @@ -737,19 +739,25 @@ public: << mName.c_str() << " expected " << inputEventTypeToString(expectedEventType) << " event, got " << inputEventTypeToString(event->getType()) << " event"; if (expectedDisplayId.has_value()) { EXPECT_EQ(expectedDisplayId, event->getDisplayId()); } switch (expectedEventType) { case AINPUT_EVENT_TYPE_KEY: { const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event); EXPECT_EQ(expectedAction, keyEvent.getAction()); EXPECT_EQ(expectedFlags, keyEvent.getFlags()); if (expectedFlags.has_value()) { EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags()); } break; } case AINPUT_EVENT_TYPE_MOTION: { const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event); EXPECT_EQ(expectedAction, motionEvent.getAction()); EXPECT_EQ(expectedFlags, motionEvent.getFlags()); if (expectedFlags.has_value()) { EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags()); } break; } case AINPUT_EVENT_TYPE_FOCUS: { Loading Loading @@ -854,6 +862,7 @@ public: mInfo.name = name; mInfo.type = InputWindowInfo::Type::APPLICATION; mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; mInfo.alpha = 1.0; mInfo.frameLeft = 0; mInfo.frameTop = 0; mInfo.frameRight = WIDTH; Loading Loading @@ -883,6 +892,12 @@ public: void setPaused(bool paused) { mInfo.paused = paused; } void setAlpha(float alpha) { mInfo.alpha = alpha; } void setTouchOcclusionMode(android::os::TouchOcclusionMode mode) { mInfo.touchOcclusionMode = mode; } void setFrame(const Rect& frame) { mInfo.frameLeft = frame.left; mInfo.frameTop = frame.top; Loading Loading @@ -928,6 +943,11 @@ public: void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT, int32_t expectedFlags = 0) { consumeAnyMotionDown(expectedDisplayId, expectedFlags); } void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt, std::optional<int32_t> expectedFlags = std::nullopt) { consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags); } Loading Loading @@ -971,8 +991,9 @@ public: mInputReceiver->consumeCaptureEvent(hasCapture); } void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId, int32_t expectedFlags) { void consumeEvent(int32_t expectedEventType, int32_t expectedAction, std::optional<int32_t> expectedDisplayId, std::optional<int32_t> expectedFlags) { ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver"; mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId, expectedFlags); Loading Loading @@ -4240,4 +4261,112 @@ TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) { mSecondWindow->consumeCaptureEvent(true); } class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest { protected: constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8; static const int32_t APP_A_UID = 10001; static const int32_t APP_B_UID = 10002; sp<FakeWindowHandle> mTouchWindow; virtual void SetUp() override { InputDispatcherTest::SetUp(); mTouchWindow = getWindow(APP_A_UID, "Touched"); mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK); mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY); } virtual void TearDown() override { InputDispatcherTest::TearDown(); mTouchWindow.clear(); } sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name, os::TouchOcclusionMode mode) { sp<FakeWindowHandle> window = getWindow(uid, name); window->setFlags(InputWindowInfo::Flag::NOT_TOUCHABLE); window->setTouchOcclusionMode(mode); return window; } sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) { std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT); // Generate an arbitrary PID based on the UID window->setOwnerInfo(1777 + (uid % 10000), uid); return window; } void touch(const std::vector<PointF>& points = {PointF{100, 200}}) { NotifyMotionArgs args = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, points); mDispatcher->notifyMotion(&args); } }; TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch(); mTouchWindow->assertNoEvents(); } TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch(); mTouchWindow->consumeAnyMotionDown(); } TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED); window->setFrame(Rect(0, 0, 50, 50)); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch({PointF{100, 100}}); mTouchWindow->consumeAnyMotionDown(); } TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_A_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch(); mTouchWindow->consumeAnyMotionDown(); } TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY); window->setAlpha(0.7); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch(); mTouchWindow->consumeAnyMotionDown(); } TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) { const sp<FakeWindowHandle>& window = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY); window->setAlpha(0.9); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, mTouchWindow}}}); touch(); mTouchWindow->assertNoEvents(); } } // namespace android::inputdispatcher