Loading libs/gui/WindowInfo.cpp +0 −8 Original line number Diff line number Diff line Loading @@ -73,14 +73,6 @@ void WindowInfo::addTouchableRegion(const Rect& region) { touchableRegion.orSelf(region); } bool WindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const { return touchableRegion.contains(x, y); } bool WindowInfo::frameContainsPoint(int32_t x, int32_t y) const { return x >= frame.left && x < frame.right && y >= frame.top && y < frame.bottom; } bool WindowInfo::supportsSplitTouch() const { return !inputConfig.test(InputConfig::PREVENT_SPLITTING); } Loading libs/gui/include/gui/WindowInfo.h +0 −4 Original line number Diff line number Diff line Loading @@ -254,10 +254,6 @@ struct WindowInfo : public Parcelable { void addTouchableRegion(const Rect& region); bool touchableRegionContainsPoint(int32_t x, int32_t y) const; bool frameContainsPoint(int32_t x, int32_t y) const; bool supportsSplitTouch() const; bool isSpy() const; Loading services/inputflinger/dispatcher/InputDispatcher.cpp +17 −4 Original line number Diff line number Diff line Loading @@ -598,6 +598,18 @@ bool windowAcceptsTouchAt(const WindowInfo& windowInfo, int32_t displayId, float return true; } // Returns true if the given window's frame can occlude pointer events at the given display // location. bool windowOccludesTouchAt(const WindowInfo& windowInfo, int displayId, float x, float y, const ui::Transform& displayTransform) { if (windowInfo.displayId != displayId) { return false; } const auto frame = displayTransform.transform(windowInfo.frame); const auto p = floor(displayTransform.transform(x, y)); return p.x >= frame.left && p.x < frame.right && p.y >= frame.top && p.y < frame.bottom; } bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) { return isFromSource(entry.source, AINPUT_SOURCE_STYLUS) && isStylusToolType(entry.pointerProperties[pointerIndex].toolType); Loading Loading @@ -3105,7 +3117,7 @@ static bool canBeObscuredBy(const sp<WindowInfoHandle>& windowHandle, * If neither of those is true, then it means the touch can be allowed. */ InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLocked( const sp<WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const { const sp<WindowInfoHandle>& windowHandle, float x, float y) const { const WindowInfo* windowInfo = windowHandle->getInfo(); int32_t displayId = windowInfo->displayId; const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); Loading @@ -3119,7 +3131,8 @@ InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLo break; // All future windows are below us. Exit early. } const WindowInfo* otherInfo = otherHandle->getInfo(); if (canBeObscuredBy(windowHandle, otherHandle) && otherInfo->frameContainsPoint(x, y) && if (canBeObscuredBy(windowHandle, otherHandle) && windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId)) && !haveSameApplicationToken(windowInfo, otherInfo)) { if (DEBUG_TOUCH_OCCLUSION) { info.debugInfo.push_back( Loading Loading @@ -3189,7 +3202,7 @@ bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionIn } bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const { float x, float y) const { int32_t displayId = windowHandle->getInfo()->displayId; const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); for (const sp<WindowInfoHandle>& otherHandle : windowHandles) { Loading @@ -3198,7 +3211,7 @@ bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& } const WindowInfo* otherInfo = otherHandle->getInfo(); if (canBeObscuredBy(windowHandle, otherHandle) && otherInfo->frameContainsPoint(x, y)) { windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId))) { return true; } } Loading services/inputflinger/dispatcher/InputDispatcher.h +2 −2 Original line number Diff line number Diff line Loading @@ -566,11 +566,11 @@ private: }; TouchOcclusionInfo computeTouchOcclusionInfoLocked( const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const const sp<android::gui::WindowInfoHandle>& windowHandle, float x, float y) const REQUIRES(mLock); bool isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const REQUIRES(mLock); bool isWindowObscuredAtPointLocked(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const REQUIRES(mLock); float x, float y) const REQUIRES(mLock); bool isWindowObscuredLocked(const sp<android::gui::WindowInfoHandle>& windowHandle) const REQUIRES(mLock); std::string dumpWindowForTouchOcclusion(const android::gui::WindowInfo* info, Loading services/inputflinger/tests/InputDispatcher_test.cpp +88 −0 Original line number Diff line number Diff line Loading @@ -5367,6 +5367,94 @@ TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) window->assertNoEvents(); } // This test verifies the occlusion detection for all rotations of the display by tapping // in different locations on the display, specifically points close to the four corners of a // window. TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) { constexpr static int32_t displayWidth = 400; constexpr static int32_t displayHeight = 800; std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication = std::make_shared<FakeApplicationHandle>(); std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); const auto rotation = GetParam(); // Set up the display with the specified rotation. const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270; const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth; const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight; const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation), logicalDisplayWidth, logicalDisplayHeight); addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform); // Create a window that not trusted. const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300); const Rect untrustedWindowFrameInDisplay = displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay); sp<FakeWindowHandle> untrustedWindow = sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow", ADISPLAY_ID_DEFAULT); untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform); untrustedWindow->setTrustedOverlay(false); untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED); untrustedWindow->setTouchable(false); untrustedWindow->setAlpha(1.0f); untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101}); addWindow(untrustedWindow); // Create a simple app window below the untrusted window. const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600); const Rect simpleAppWindowFrameInDisplay = displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay); sp<FakeWindowHandle> simpleAppWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow", ADISPLAY_ID_DEFAULT); simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform); simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202}); addWindow(simpleAppWindow); // The following points in logical display space should be inside the untrusted window, so // the simple window could not receive events that coordinate is these point. static const std::array<vec2, 4> untrustedPoints{ {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}}; for (const auto untrustedPoint : untrustedPoints) { const vec2 p = displayTransform.inverse().transform(untrustedPoint); const PointF pointInDisplaySpace{p.x, p.y}; mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInDisplaySpace})); mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInDisplaySpace})); } untrustedWindow->assertNoEvents(); simpleAppWindow->assertNoEvents(); // The following points in logical display space should be outside the untrusted window, so // the simple window should receive events that coordinate is these point. static const std::array<vec2, 5> trustedPoints{ {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}}; for (const auto trustedPoint : trustedPoints) { const vec2 p = displayTransform.inverse().transform(trustedPoint); const PointF pointInDisplaySpace{p.x, p.y}; mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInDisplaySpace})); simpleAppWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED); mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInDisplaySpace})); simpleAppWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED); } untrustedWindow->assertNoEvents(); } // Run the precision tests for all rotations. INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests, InputDispatcherDisplayOrientationFixture, Loading Loading
libs/gui/WindowInfo.cpp +0 −8 Original line number Diff line number Diff line Loading @@ -73,14 +73,6 @@ void WindowInfo::addTouchableRegion(const Rect& region) { touchableRegion.orSelf(region); } bool WindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const { return touchableRegion.contains(x, y); } bool WindowInfo::frameContainsPoint(int32_t x, int32_t y) const { return x >= frame.left && x < frame.right && y >= frame.top && y < frame.bottom; } bool WindowInfo::supportsSplitTouch() const { return !inputConfig.test(InputConfig::PREVENT_SPLITTING); } Loading
libs/gui/include/gui/WindowInfo.h +0 −4 Original line number Diff line number Diff line Loading @@ -254,10 +254,6 @@ struct WindowInfo : public Parcelable { void addTouchableRegion(const Rect& region); bool touchableRegionContainsPoint(int32_t x, int32_t y) const; bool frameContainsPoint(int32_t x, int32_t y) const; bool supportsSplitTouch() const; bool isSpy() const; Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +17 −4 Original line number Diff line number Diff line Loading @@ -598,6 +598,18 @@ bool windowAcceptsTouchAt(const WindowInfo& windowInfo, int32_t displayId, float return true; } // Returns true if the given window's frame can occlude pointer events at the given display // location. bool windowOccludesTouchAt(const WindowInfo& windowInfo, int displayId, float x, float y, const ui::Transform& displayTransform) { if (windowInfo.displayId != displayId) { return false; } const auto frame = displayTransform.transform(windowInfo.frame); const auto p = floor(displayTransform.transform(x, y)); return p.x >= frame.left && p.x < frame.right && p.y >= frame.top && p.y < frame.bottom; } bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) { return isFromSource(entry.source, AINPUT_SOURCE_STYLUS) && isStylusToolType(entry.pointerProperties[pointerIndex].toolType); Loading Loading @@ -3105,7 +3117,7 @@ static bool canBeObscuredBy(const sp<WindowInfoHandle>& windowHandle, * If neither of those is true, then it means the touch can be allowed. */ InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLocked( const sp<WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const { const sp<WindowInfoHandle>& windowHandle, float x, float y) const { const WindowInfo* windowInfo = windowHandle->getInfo(); int32_t displayId = windowInfo->displayId; const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); Loading @@ -3119,7 +3131,8 @@ InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLo break; // All future windows are below us. Exit early. } const WindowInfo* otherInfo = otherHandle->getInfo(); if (canBeObscuredBy(windowHandle, otherHandle) && otherInfo->frameContainsPoint(x, y) && if (canBeObscuredBy(windowHandle, otherHandle) && windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId)) && !haveSameApplicationToken(windowInfo, otherInfo)) { if (DEBUG_TOUCH_OCCLUSION) { info.debugInfo.push_back( Loading Loading @@ -3189,7 +3202,7 @@ bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionIn } bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const { float x, float y) const { int32_t displayId = windowHandle->getInfo()->displayId; const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); for (const sp<WindowInfoHandle>& otherHandle : windowHandles) { Loading @@ -3198,7 +3211,7 @@ bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& } const WindowInfo* otherInfo = otherHandle->getInfo(); if (canBeObscuredBy(windowHandle, otherHandle) && otherInfo->frameContainsPoint(x, y)) { windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId))) { return true; } } Loading
services/inputflinger/dispatcher/InputDispatcher.h +2 −2 Original line number Diff line number Diff line Loading @@ -566,11 +566,11 @@ private: }; TouchOcclusionInfo computeTouchOcclusionInfoLocked( const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const const sp<android::gui::WindowInfoHandle>& windowHandle, float x, float y) const REQUIRES(mLock); bool isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const REQUIRES(mLock); bool isWindowObscuredAtPointLocked(const sp<android::gui::WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const REQUIRES(mLock); float x, float y) const REQUIRES(mLock); bool isWindowObscuredLocked(const sp<android::gui::WindowInfoHandle>& windowHandle) const REQUIRES(mLock); std::string dumpWindowForTouchOcclusion(const android::gui::WindowInfo* info, Loading
services/inputflinger/tests/InputDispatcher_test.cpp +88 −0 Original line number Diff line number Diff line Loading @@ -5367,6 +5367,94 @@ TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) window->assertNoEvents(); } // This test verifies the occlusion detection for all rotations of the display by tapping // in different locations on the display, specifically points close to the four corners of a // window. TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) { constexpr static int32_t displayWidth = 400; constexpr static int32_t displayHeight = 800; std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication = std::make_shared<FakeApplicationHandle>(); std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); const auto rotation = GetParam(); // Set up the display with the specified rotation. const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270; const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth; const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight; const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation), logicalDisplayWidth, logicalDisplayHeight); addDisplayInfo(ADISPLAY_ID_DEFAULT, displayTransform); // Create a window that not trusted. const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300); const Rect untrustedWindowFrameInDisplay = displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay); sp<FakeWindowHandle> untrustedWindow = sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow", ADISPLAY_ID_DEFAULT); untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform); untrustedWindow->setTrustedOverlay(false); untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED); untrustedWindow->setTouchable(false); untrustedWindow->setAlpha(1.0f); untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101}); addWindow(untrustedWindow); // Create a simple app window below the untrusted window. const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600); const Rect simpleAppWindowFrameInDisplay = displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay); sp<FakeWindowHandle> simpleAppWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow", ADISPLAY_ID_DEFAULT); simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform); simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202}); addWindow(simpleAppWindow); // The following points in logical display space should be inside the untrusted window, so // the simple window could not receive events that coordinate is these point. static const std::array<vec2, 4> untrustedPoints{ {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}}; for (const auto untrustedPoint : untrustedPoints) { const vec2 p = displayTransform.inverse().transform(untrustedPoint); const PointF pointInDisplaySpace{p.x, p.y}; mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInDisplaySpace})); mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInDisplaySpace})); } untrustedWindow->assertNoEvents(); simpleAppWindow->assertNoEvents(); // The following points in logical display space should be outside the untrusted window, so // the simple window should receive events that coordinate is these point. static const std::array<vec2, 5> trustedPoints{ {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}}; for (const auto trustedPoint : trustedPoints) { const vec2 p = displayTransform.inverse().transform(trustedPoint); const PointF pointInDisplaySpace{p.x, p.y}; mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInDisplaySpace})); simpleAppWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED); mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {pointInDisplaySpace})); simpleAppWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED); } untrustedWindow->assertNoEvents(); } // Run the precision tests for all rotations. INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests, InputDispatcherDisplayOrientationFixture, Loading