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

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

Only send events to windows with pointers

Due to the recent refactor, some of the windows with only hovering
pointers are getting persisted inside TouchState. This is the case for
the hovering pointers from mouse, for example. Mouse usually never
leaves the screen, so it's always inside some window.

However, we are still currently iterating over TouchedWindows inside
the TouchState in order to determine which targets should receive the
current entry.

That means that the windows that are hovered over will always be there,
which is not something that we want. It would cause the events to go
to windows that are not directly getting touched.

To avoid this, make sure that the pointers are indeed supposed to be
going to the current window. In a future refactor, we will store the pointers
per-device, as well.

The added test reproduces a condition where we crash due to mismatching
downtimes.
There are few issues that it exposes.

1) We currently use hover events for setting the downtime of a window,
   which we shouldn't do.
2) If a window is not receiving the events from the current device, it
   shouldn't be in the dispatching list. So we should not be sending the
   events there to begin with.

Bug: 266455987
Test: m inputflinger_tests && $ANDROID_HOST_OUT/nativetest64/inputflinger_tests/inputflinger_tests --gtest_filter="*HoverFromLeftToRightAndTap*"
Change-Id: Ic0d2a1ed6d053e18077bc7216b1ce02e88017b4a
parent 060f82be
Loading
Loading
Loading
Loading
+13 −3
Original line number Original line Diff line number Diff line
@@ -2303,8 +2303,13 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
                pointerIds.markBit(entry.pointerProperties[pointerIndex].id);
                pointerIds.markBit(entry.pointerProperties[pointerIndex].id);
            }
            }


            const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN ||
                    maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN;

            tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds,
            tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds,
                                             entry.eventTime);
                                             isDownOrPointerDown
                                                     ? std::make_optional(entry.eventTime)
                                                     : std::nullopt);


            // If this is the pointer going down and the touched window has a wallpaper
            // If this is the pointer going down and the touched window has a wallpaper
            // then also add the touched wallpaper windows so they are locked in for the duration
            // then also add the touched wallpaper windows so they are locked in for the duration
@@ -2312,8 +2317,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
            // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
            // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
            // engine only supports touch events.  We would need to add a mechanism similar
            // engine only supports touch events.  We would need to add a mechanism similar
            // to View.onGenericMotionEvent to enable wallpapers to handle these events.
            // to View.onGenericMotionEvent to enable wallpapers to handle these events.
            if (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
            if (isDownOrPointerDown) {
                maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) {
                if (targetFlags.test(InputTarget::Flags::FOREGROUND) &&
                if (targetFlags.test(InputTarget::Flags::FOREGROUND) &&
                    windowHandle->getInfo()->inputConfig.test(
                    windowHandle->getInfo()->inputConfig.test(
                            gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
                            gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
@@ -2517,6 +2521,12 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
    // Success!  Output targets from the touch state.
    // Success!  Output targets from the touch state.
    tempTouchState.clearWindowsWithoutPointers();
    tempTouchState.clearWindowsWithoutPointers();
    for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
    for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
        if (touchedWindow.pointerIds.isEmpty() &&
            !touchedWindow.hasHoveringPointers(entry.deviceId)) {
            // Windows with hovering pointers are getting persisted inside TouchState.
            // Do not send this event to those windows.
            continue;
        }
        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
        addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
                              touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
                              touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
                              targets);
                              targets);
+3 −3
Original line number Original line Diff line number Diff line
@@ -63,7 +63,7 @@ void TouchState::clearWindowsWithoutPointers() {


void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
                                   ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds,
                                   ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds,
                                   std::optional<nsecs_t> eventTime) {
                                   std::optional<nsecs_t> firstDownTimeInTarget) {
    for (TouchedWindow& touchedWindow : windows) {
    for (TouchedWindow& touchedWindow : windows) {
        // We do not compare windows by token here because two windows that share the same token
        // We do not compare windows by token here because two windows that share the same token
        // may have a different transform
        // may have a different transform
@@ -77,7 +77,7 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
            // the window.
            // the window.
            touchedWindow.pointerIds.value |= pointerIds.value;
            touchedWindow.pointerIds.value |= pointerIds.value;
            if (!touchedWindow.firstDownTimeInTarget.has_value()) {
            if (!touchedWindow.firstDownTimeInTarget.has_value()) {
                touchedWindow.firstDownTimeInTarget = eventTime;
                touchedWindow.firstDownTimeInTarget = firstDownTimeInTarget;
            }
            }
            return;
            return;
        }
        }
@@ -86,7 +86,7 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
    touchedWindow.windowHandle = windowHandle;
    touchedWindow.windowHandle = windowHandle;
    touchedWindow.targetFlags = targetFlags;
    touchedWindow.targetFlags = targetFlags;
    touchedWindow.pointerIds = pointerIds;
    touchedWindow.pointerIds = pointerIds;
    touchedWindow.firstDownTimeInTarget = eventTime;
    touchedWindow.firstDownTimeInTarget = firstDownTimeInTarget;
    windows.push_back(touchedWindow);
    windows.push_back(touchedWindow);
}
}


+1 −1
Original line number Original line Diff line number Diff line
@@ -47,7 +47,7 @@ struct TouchState {
                                        const sp<android::gui::WindowInfoHandle>& windowHandle);
                                        const sp<android::gui::WindowInfoHandle>& windowHandle);
    void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
    void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
                           ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds,
                           ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds,
                           std::optional<nsecs_t> eventTime = std::nullopt);
                           std::optional<nsecs_t> firstDownTimeInTarget = std::nullopt);
    void addHoveringPointerToWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
    void addHoveringPointerToWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
                                    int32_t deviceId, int32_t hoveringPointerId);
                                    int32_t deviceId, int32_t hoveringPointerId);
    void removeHoveringPointer(int32_t deviceId, int32_t hoveringPointerId);
    void removeHoveringPointer(int32_t deviceId, int32_t hoveringPointerId);
+4 −0
Original line number Original line Diff line number Diff line
@@ -29,6 +29,10 @@ bool TouchedWindow::hasHoveringPointers() const {
    return !mHoveringPointerIdsByDevice.empty();
    return !mHoveringPointerIdsByDevice.empty();
}
}


bool TouchedWindow::hasHoveringPointers(int32_t deviceId) const {
    return mHoveringPointerIdsByDevice.find(deviceId) != mHoveringPointerIdsByDevice.end();
}

void TouchedWindow::clearHoveringPointers() {
void TouchedWindow::clearHoveringPointers() {
    mHoveringPointerIdsByDevice.clear();
    mHoveringPointerIdsByDevice.clear();
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ struct TouchedWindow {
    std::optional<nsecs_t> firstDownTimeInTarget;
    std::optional<nsecs_t> firstDownTimeInTarget;


    bool hasHoveringPointers() const;
    bool hasHoveringPointers() const;
    bool hasHoveringPointers(int32_t deviceId) const;


    bool hasHoveringPointer(int32_t deviceId, int32_t pointerId) const;
    bool hasHoveringPointer(int32_t deviceId, int32_t pointerId) const;
    void addHoveringPointer(int32_t deviceId, int32_t pointerId);
    void addHoveringPointer(int32_t deviceId, int32_t pointerId);
Loading