Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88f35517 authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Android (Google) Code Review
Browse files

Merge "Move occlusion detection into logical space" into main

parents 64077b5a 5e5645e8
Loading
Loading
Loading
Loading
+0 −8
Original line number Original line Diff line number Diff line
@@ -73,14 +73,6 @@ void WindowInfo::addTouchableRegion(const Rect& region) {
    touchableRegion.orSelf(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 {
bool WindowInfo::supportsSplitTouch() const {
    return !inputConfig.test(InputConfig::PREVENT_SPLITTING);
    return !inputConfig.test(InputConfig::PREVENT_SPLITTING);
}
}
+0 −4
Original line number Original line Diff line number Diff line
@@ -254,10 +254,6 @@ struct WindowInfo : public Parcelable {


    void addTouchableRegion(const Rect& region);
    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 supportsSplitTouch() const;


    bool isSpy() const;
    bool isSpy() const;
+17 −4
Original line number Original line Diff line number Diff line
@@ -598,6 +598,18 @@ bool windowAcceptsTouchAt(const WindowInfo& windowInfo, int32_t displayId, float
    return true;
    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) {
bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) {
    return isFromSource(entry.source, AINPUT_SOURCE_STYLUS) &&
    return isFromSource(entry.source, AINPUT_SOURCE_STYLUS) &&
            isStylusToolType(entry.pointerProperties[pointerIndex].toolType);
            isStylusToolType(entry.pointerProperties[pointerIndex].toolType);
@@ -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.
 * If neither of those is true, then it means the touch can be allowed.
 */
 */
InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLocked(
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();
    const WindowInfo* windowInfo = windowHandle->getInfo();
    int32_t displayId = windowInfo->displayId;
    int32_t displayId = windowInfo->displayId;
    const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
    const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
@@ -3119,7 +3131,8 @@ InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLo
            break; // All future windows are below us. Exit early.
            break; // All future windows are below us. Exit early.
        }
        }
        const WindowInfo* otherInfo = otherHandle->getInfo();
        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)) {
            !haveSameApplicationToken(windowInfo, otherInfo)) {
            if (DEBUG_TOUCH_OCCLUSION) {
            if (DEBUG_TOUCH_OCCLUSION) {
                info.debugInfo.push_back(
                info.debugInfo.push_back(
@@ -3189,7 +3202,7 @@ bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionIn
}
}


bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& windowHandle,
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;
    int32_t displayId = windowHandle->getInfo()->displayId;
    const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
    const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
    for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
    for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
@@ -3198,7 +3211,7 @@ bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>&
        }
        }
        const WindowInfo* otherInfo = otherHandle->getInfo();
        const WindowInfo* otherInfo = otherHandle->getInfo();
        if (canBeObscuredBy(windowHandle, otherHandle) &&
        if (canBeObscuredBy(windowHandle, otherHandle) &&
            otherInfo->frameContainsPoint(x, y)) {
            windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId))) {
            return true;
            return true;
        }
        }
    }
    }
+2 −2
Original line number Original line Diff line number Diff line
@@ -566,11 +566,11 @@ private:
    };
    };


    TouchOcclusionInfo computeTouchOcclusionInfoLocked(
    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);
            REQUIRES(mLock);
    bool isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const REQUIRES(mLock);
    bool isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const REQUIRES(mLock);
    bool isWindowObscuredAtPointLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
    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
    bool isWindowObscuredLocked(const sp<android::gui::WindowInfoHandle>& windowHandle) const
            REQUIRES(mLock);
            REQUIRES(mLock);
    std::string dumpWindowForTouchOcclusion(const android::gui::WindowInfo* info,
    std::string dumpWindowForTouchOcclusion(const android::gui::WindowInfo* info,
+88 −0
Original line number Original line Diff line number Diff line
@@ -5367,6 +5367,94 @@ TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations)
    window->assertNoEvents();
    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.
// Run the precision tests for all rotations.
INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
                         InputDispatcherDisplayOrientationFixture,
                         InputDispatcherDisplayOrientationFixture,