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

Commit a3fe664c authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Always split touches

In this CL, we are force all windows to use FLAG_SPLIT_TOUCH. This is
needed to avoid complex interactions between this flag and the spy
windows functionality. The old behaviour is likely mostly a historical
artifact, and was not originally intended. With the features like
freeform windows, split screen, and spy windows now possible, we should
always split touch to also avoid potential security issues about
receiving touches outside of your window.

If the functionality of rejecting partial gestures is indeed necessary,
then it will be introduced via a new flag that's only usable by
privileged windows.

Bug: 239934827
Test: atest inputflinger_tests
Flag: com.android.input.flags.split_all_touches
Change-Id: I579651e1309012a6db96730548c12f032c43d88a
parent 0f499e82
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -36,6 +36,13 @@ flag {
  bug: "211379801"
}

flag {
  name: "split_all_touches"
  namespace: "input"
  description: "Set FLAG_SPLIT_TOUCHES to true for all windows, regardless of what they specify. This is essentially deprecating this flag by forcefully enabling the split functionality"
  bug: "239934827"
}

flag {
  name: "a11y_crash_on_inconsistent_event_stream"
  namespace: "accessibility"
+19 −5
Original line number Diff line number Diff line
@@ -2448,12 +2448,19 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio
        if (isDown) {
            targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle, pointer.id);
        }
        LOG_IF(INFO, newTouchedWindowHandle == nullptr)
                << "No new touched window at (" << std::format("{:.1f}, {:.1f}", x, y)
                << ") in display " << displayId;
        // Handle the case where we did not find a window.
        if (!input_flags::split_all_touches()) {
            // If we are force splitting all touches, then touches outside of the window should
            // be dropped, even if this device already has pointers down in another window.
            if (newTouchedWindowHandle == nullptr) {
            ALOGD("No new touched window at (%.1f, %.1f) in display %s", x, y,
                  displayId.toString().c_str());
            // Try to assign the pointer to the first foreground window we find, if there is one.
            newTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle(entry.deviceId);
                // Try to assign the pointer to the first foreground window we find, if there is
                // one.
                newTouchedWindowHandle =
                        tempTouchState.getFirstForegroundWindowHandle(entry.deviceId);
            }
        }

        // Verify targeted injection.
@@ -7007,6 +7014,13 @@ void InputDispatcher::onWindowInfosChanged(const gui::WindowInfosUpdate& update)
    for (const auto& info : update.windowInfos) {
        handlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>());
        handlesPerDisplay[info.displayId].push_back(sp<WindowInfoHandle>::make(info));
        if (input_flags::split_all_touches()) {
            handlesPerDisplay[info.displayId]
                    .back()
                    ->editInfo()
                    ->setInputConfig(android::gui::WindowInfo::InputConfig::PREVENT_SPLITTING,
                                     false);
        }
    }

    { // acquire lock
+7 −0
Original line number Diff line number Diff line
@@ -4168,6 +4168,7 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
 * the event routing because the first window prevents splitting.
 */
TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTimeForNewWindow) {
    SCOPED_FLAG_OVERRIDE(split_all_touches, false);
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window1 =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
@@ -4225,6 +4226,7 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTimeForNewWindow) {
 * (and the touch occurred outside of the bounds of window1).
 */
TEST_F(InputDispatcherTest, SplitTouchesDropsEventForNonSplittableSecondWindow) {
    SCOPED_FLAG_OVERRIDE(split_all_touches, false);
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window1 =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
@@ -4600,6 +4602,7 @@ class SpyThatPreventsSplittingWithApplicationFixture : public InputDispatcherTes
 * This test attempts to reproduce a crash in the dispatcher.
 */
TEST_P(SpyThatPreventsSplittingWithApplicationFixture, SpyThatPreventsSplittingWithApplication) {
    SCOPED_FLAG_OVERRIDE(split_all_touches, false);
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
@@ -5583,6 +5586,7 @@ TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
}
TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
    SCOPED_FLAG_OVERRIDE(split_all_touches, false);
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
@@ -5628,6 +5632,7 @@ TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
 * "incomplete" gestures.
 */
TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
    SCOPED_FLAG_OVERRIDE(split_all_touches, false);
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> leftWindow =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
@@ -5665,6 +5670,7 @@ TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
 * This test attempts to reproduce a crash.
 */
TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
    SCOPED_FLAG_OVERRIDE(split_all_touches, false);
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> leftWindow =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
@@ -8411,6 +8417,7 @@ TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
 * the previous window should receive this event and not be dropped.
 */
TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
    SCOPED_FLAG_OVERRIDE(split_all_touches, false);
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
                                                             ui::LogicalDisplayId::DEFAULT);