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

Commit 0f6558d6 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Do not slip touch into window with same input channel

When two windows have the same input channel, do not slip touch from one
of them into the other. We don't have a use case for that, and
supporting this behaviour would be harder than simply disabling it.

Without slipping, the input channel also receives a continuous gesture,
which is generally desirable. The original window may not know that
there's a clone out there with the same input channel, and therefore may
not know to remove FLAG_SLIPPERY whenever it desires to receive a
continuous gesture.

Bug: 274073185
Test: m inputflinger_tests && $ANDROID_HOST_OUT/nativetest64/inputflinger_tests/inputflinger_tests
Change-Id: I577724c1c2e77928e695c250b5f5fbe8f1592a2f
parent fe46a177
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -2402,6 +2402,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
            const bool isStylus = isPointerFromStylus(entry, /*pointerIndex=*/0);
            sp<WindowInfoHandle> oldTouchedWindowHandle =
                    tempTouchState.getFirstForegroundWindowHandle();
            LOG_ALWAYS_FATAL_IF(oldTouchedWindowHandle == nullptr);
            auto [newTouchedWindowHandle, _] = findTouchedWindowAtLocked(displayId, x, y, isStylus);

            // Verify targeted injection.
@@ -2417,13 +2418,11 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
                newTouchedWindowHandle = nullptr;
            }

            if (oldTouchedWindowHandle != newTouchedWindowHandle &&
                oldTouchedWindowHandle != nullptr && newTouchedWindowHandle != nullptr) {
                if (DEBUG_FOCUS) {
            if (!haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) {
                ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32,
                      oldTouchedWindowHandle->getName().c_str(),
                      newTouchedWindowHandle->getName().c_str(), displayId);
                }

                // Make a slippery exit from the old window.
                std::bitset<MAX_POINTER_ID + 1> pointerIds;
                const int32_t pointerId = entry.pointerProperties[0].id;
+22 −0
Original line number Diff line number Diff line
@@ -6140,6 +6140,28 @@ TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithSc
    touchAndAssertPositions(AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
}

/**
 * When one of the windows is slippery, the touch should not slip into the other window with the
 * same input channel.
 */
TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
    mWindow1->setSlippery(true);
    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow1, mWindow2}}});

    // Touch down in window 1
    mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
                                                 ADISPLAY_ID_DEFAULT, {{50, 50}}));
    consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});

    // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
    // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
    // getting generated.
    mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
                                                 ADISPLAY_ID_DEFAULT, {{150, 150}}));

    consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
}

class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
    virtual void SetUp() override {
        InputDispatcherTest::SetUp();