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

Commit a05506e1 authored by Harry Cutts's avatar Harry Cutts Committed by Automerger Merge Worker
Browse files

Merge "InputDispatcher: Only send touchpad nav gestures to trusted overlays"...

Merge "InputDispatcher: Only send touchpad nav gestures to trusted overlays" into udc-dev am: 89b675ef

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/23114716



Change-Id: Ie47c85a9df809dbe5db4fdaa55b74d0b9695da6f
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 330f2730 89b675ef
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -681,6 +681,25 @@ std::vector<T>& operator+=(std::vector<T>& left, const std::vector<T>& right) {
    return left;
}

// Filter windows in a TouchState and targets in a vector to remove untrusted windows/targets from
// both.
void filterUntrustedTargets(TouchState& touchState, std::vector<InputTarget>& targets) {
    std::erase_if(touchState.windows, [&](const TouchedWindow& window) {
        if (!window.windowHandle->getInfo()->inputConfig.test(
                    WindowInfo::InputConfig::TRUSTED_OVERLAY)) {
            // In addition to TouchState, erase this window from the input targets! We don't have a
            // good way to do this today except by adding a nested loop.
            // TODO(b/282025641): simplify this code once InputTargets are being identified
            // separately from TouchedWindows.
            std::erase_if(targets, [&](const InputTarget& target) {
                return target.inputChannel->getConnectionToken() == window.windowHandle->getToken();
            });
            return true;
        }
        return false;
    });
}

} // namespace

// --- InputDispatcher ---
@@ -2588,6 +2607,14 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
        }
    }

    // If this is a touchpad navigation gesture, it needs to only be sent to trusted targets, as we
    // only want the system UI to handle these gestures.
    const bool isTouchpadNavGesture = isFromSource(entry.source, AINPUT_SOURCE_MOUSE) &&
            entry.classification == MotionClassification::MULTI_FINGER_SWIPE;
    if (isTouchpadNavGesture) {
        filterUntrustedTargets(/* byref */ tempTouchState, /* byref */ targets);
    }

    // Output targets from the touch state.
    for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
        if (touchedWindow.pointerIds.none() && !touchedWindow.hasHoveringPointers(entry.deviceId)) {
@@ -2595,6 +2622,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
            // Do not send this event to those windows.
            continue;
        }

        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
                              touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
                              targets);
+129 −1
Original line number Diff line number Diff line
@@ -86,6 +86,8 @@ static constexpr int32_t POINTER_0_UP =
        AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
static constexpr int32_t POINTER_1_UP =
        AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
static constexpr int32_t POINTER_2_UP =
        AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);

// The default pid and uid for windows created on the primary display by the test.
static constexpr int32_t WINDOW_PID = 999;
@@ -1660,6 +1662,11 @@ public:
        return *this;
    }

    MotionArgsBuilder& classification(MotionClassification classification) {
        mClassification = classification;
        return *this;
    }

    NotifyMotionArgs build() {
        std::vector<PointerProperties> pointerProperties;
        std::vector<PointerCoords> pointerCoords;
@@ -1678,7 +1685,7 @@ public:

        NotifyMotionArgs args(InputEvent::nextId(), mEventTime, /*readTime=*/mEventTime, mDeviceId,
                              mSource, mDisplayId, mPolicyFlags, mAction, mActionButton, mFlags,
                              AMETA_NONE, mButtonState, MotionClassification::NONE, /*edgeFlags=*/0,
                              AMETA_NONE, mButtonState, mClassification, /*edgeFlags=*/0,
                              mPointers.size(), pointerProperties.data(), pointerCoords.data(),
                              /*xPrecision=*/0, /*yPrecision=*/0, mRawXCursorPosition,
                              mRawYCursorPosition, mDownTime, /*videoFrames=*/{});
@@ -1697,6 +1704,7 @@ private:
    int32_t mActionButton{0};
    int32_t mButtonState{0};
    int32_t mFlags{0};
    MotionClassification mClassification{MotionClassification::NONE};
    float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
    float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};

@@ -4003,6 +4011,126 @@ TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
    EXPECT_EQ(-10, event->getY(1)); // -50 + 40
}

TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
    window->setFrame(Rect(0, 0, 400, 400));
    sp<FakeWindowHandle> trustedOverlay =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
                                       ADISPLAY_ID_DEFAULT);
    trustedOverlay->setSpy(true);
    trustedOverlay->setTrustedOverlay(true);

    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {trustedOverlay, window}}});

    // Start a three-finger touchpad swipe
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
                                      .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());

    trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
    trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
    trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));

    // Move the swipe a bit
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
                                      .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());

    trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));

    // End the swipe
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
                                      .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());

    trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
    trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
    trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));

    window->assertNoEvents();
}

TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
    window->setFrame(Rect(0, 0, 400, 400));
    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});

    // Start a three-finger touchpad swipe
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
                                      .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());

    // Move the swipe a bit
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
                                      .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());

    // End the swipe
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
                                      .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());
    mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
                                      .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
                                      .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
                                      .classification(MotionClassification::MULTI_FINGER_SWIPE)
                                      .build());

    window->assertNoEvents();
}

/**
 * Ensure the correct coordinate spaces are used by InputDispatcher.
 *