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 Diff line number Diff line
@@ -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);
}
+0 −4
Original line number Diff line number Diff line
@@ -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;
+17 −4
Original line number Diff line number Diff line
@@ -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);
@@ -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);
@@ -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(
@@ -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) {
@@ -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;
        }
    }
+2 −2
Original line number Diff line number Diff line
@@ -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,
+88 −0
Original line number Diff line number Diff line
@@ -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,