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

Commit daa995cc authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Associate device id with isSlippery" into main

parents af567a88 49b2b20f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2619,7 +2619,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(

        // Check whether touches should slip outside of the current foreground window.
        if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.getPointerCount() == 1 &&
            tempTouchState.isSlippery()) {
            tempTouchState.isSlippery(entry.deviceId)) {
            const auto [x, y] = resolveTouchedPosition(entry);
            const bool isStylus = isPointerFromStylus(entry, /*pointerIndex=*/0);
            sp<WindowInfoHandle> oldTouchedWindowHandle =
+4 −1
Original line number Diff line number Diff line
@@ -192,10 +192,13 @@ sp<WindowInfoHandle> TouchState::getFirstForegroundWindowHandle(DeviceId deviceI
    return nullptr;
}

bool TouchState::isSlippery() const {
bool TouchState::isSlippery(DeviceId deviceId) const {
    // Must have exactly one foreground window.
    bool haveSlipperyForegroundWindow = false;
    for (const TouchedWindow& window : windows) {
        if (!window.hasTouchingPointers(deviceId)) {
            continue;
        }
        if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) {
            if (haveSlipperyForegroundWindow ||
                !window.windowHandle->getInfo()->inputConfig.test(
+1 −1
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ struct TouchState {
    void cancelPointersForNonPilferingWindows();

    sp<android::gui::WindowInfoHandle> getFirstForegroundWindowHandle(DeviceId deviceId) const;
    bool isSlippery() const;
    bool isSlippery(DeviceId deviceId) const;
    sp<android::gui::WindowInfoHandle> getWallpaperWindow() const;
    const TouchedWindow& getTouchedWindow(
            const sp<android::gui::WindowInfoHandle>& windowHandle) const;
+148 −0
Original line number Diff line number Diff line
@@ -7328,6 +7328,154 @@ TEST_F(InputDispatcherTest, InjectedTouchSlips) {
    appearingWindow->assertNoEvents();
}
/**
 * Three windows:
 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
 * - right window
 * - spy window
 * The three windows do not overlap.
 *
 * We have two devices reporting events:
 * - Device A reports ACTION_DOWN, which lands in the left window
 * - Device B reports ACTION_DOWN, which lands in the spy window.
 * - Now, device B reports ACTION_MOVE events which move to the right window.
 *
 * The right window should not receive any events because the spy window is not a foreground window,
 * and also it does not support slippery touches.
 */
TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> leftWindow =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
                                       ADISPLAY_ID_DEFAULT);
    leftWindow->setFrame(Rect(0, 0, 100, 100));
    leftWindow->setSlippery(true);
    sp<FakeWindowHandle> rightWindow =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
                                       ADISPLAY_ID_DEFAULT);
    rightWindow->setFrame(Rect(100, 0, 200, 100));
    sp<FakeWindowHandle> spyWindow =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window", ADISPLAY_ID_DEFAULT);
    spyWindow->setFrame(Rect(200, 0, 300, 100));
    spyWindow->setSpy(true);
    spyWindow->setTrustedOverlay(true);
    mDispatcher->onWindowInfosChanged(
            {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
    const DeviceId deviceA = 9;
    const DeviceId deviceB = 3;
    // Tap on left window with device A
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
                                      .deviceId(deviceA)
                                      .build());
    leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
    // Tap on spy window with device B
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
                                      .deviceId(deviceB)
                                      .build());
    spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
    // Move to right window with device B. Touches should not slip to the right window, because spy
    // window is not a foreground window, and it does not have FLAG_SLIPPERY
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
                                      .deviceId(deviceB)
                                      .build());
    leftWindow->assertNoEvents();
    rightWindow->assertNoEvents();
    spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
}
/**
 * Three windows arranged horizontally and without any overlap.
 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
 *
 * We have two devices reporting events:
 * - Device A reports ACTION_DOWN which lands in the left window
 * - Device B reports ACTION_DOWN which lands in the right window
 * - Device B reports ACTION_MOVE that shifts to the middle window.
 * This should cause touches for Device B to slip from the right window to the middle window.
 * The right window should receive ACTION_CANCEL for device B and the
 * middle window should receive down event for Device B.
 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
 */
TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> leftWindow =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
                                       ADISPLAY_ID_DEFAULT);
    leftWindow->setFrame(Rect(0, 0, 100, 100));
    leftWindow->setSlippery(true);
    sp<FakeWindowHandle> middleWindow =
            sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
                                       ADISPLAY_ID_DEFAULT);
    middleWindow->setFrame(Rect(100, 0, 200, 100));
    sp<FakeWindowHandle> rightWindow =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
                                       ADISPLAY_ID_DEFAULT);
    rightWindow->setFrame(Rect(200, 0, 300, 100));
    rightWindow->setSlippery(true);
    mDispatcher->onWindowInfosChanged(
            {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
             {},
             0,
             0});
    const DeviceId deviceA = 9;
    const DeviceId deviceB = 3;
    // Tap on left window with device A
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
                                      .deviceId(deviceA)
                                      .build());
    leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
    // Tap on right window with device B
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
                                      .deviceId(deviceB)
                                      .build());
    rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
    // Move to middle window with device B. Touches should slip to middle window, because right
    // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
                                      .deviceId(deviceB)
                                      .build());
    rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
    middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
    // Move to middle window with device A. Touches should slip to middle window, because left
    // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
                                      .deviceId(deviceA)
                                      .build());
    leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
    middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
    // Ensure that middle window can receive the remaining move events.
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
                                      .deviceId(deviceB)
                                      .build());
    leftWindow->assertNoEvents();
    middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
    rightWindow->assertNoEvents();
}
TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
    using Uid = gui::Uid;
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();