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

Commit 1ff00cce authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

TouchedWindow: store tool type in addition to pointer id

Before this CL, we only stored the touching pointer id's inside
TouchWindow. However, it is also necessary to know which of the touching
pointers are touch vs stylus. This would allow us in a later CL to
determine whether the stylus is currently down anywhere on screen.

In this CL, instead of storing just the pointer ids, store
PointerProperties in a vector. This includes the pointer id and the
tooltype.

There should be no behaviour change in this CL.

Bug: 316225294
Test: TEST=inputflinger_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST
Change-Id: I7fb2bbd46e7da7e085679ee16da3a53773931875
parent 96a1557c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -515,6 +515,8 @@ struct PointerProperties {
    PointerProperties& operator=(const PointerProperties&) = default;
};

std::ostream& operator<<(std::ostream& out, const PointerProperties& properties);

// TODO(b/211379801) : Use a strong type from ftl/mixins.h instead
using DeviceId = int32_t;

+5 −0
Original line number Diff line number Diff line
@@ -379,6 +379,11 @@ std::ostream& operator<<(std::ostream& out, const KeyEvent& event) {
    return out;
}

std::ostream& operator<<(std::ostream& out, const PointerProperties& properties) {
    out << "Pointer(id=" << properties.id << ", " << ftl::enum_string(properties.toolType) << ")";
    return out;
}

// --- PointerCoords ---

float PointerCoords::getAxisValue(int32_t axis) const {
+45 −39
Original line number Diff line number Diff line
@@ -253,6 +253,14 @@ Result<void> validateInputEvent(const InputEvent& event) {
    }
}

std::bitset<MAX_POINTER_ID + 1> getPointerIds(const std::vector<PointerProperties>& pointers) {
    std::bitset<MAX_POINTER_ID + 1> pointerIds;
    for (const PointerProperties& pointer : pointers) {
        pointerIds.set(pointer.id);
    }
    return pointerIds;
}

std::string dumpRegion(const Region& region) {
    if (region.isEmpty()) {
        return "<empty>";
@@ -631,15 +639,15 @@ std::vector<TouchedWindow> getHoveringWindowsLocked(const TouchState* oldState,
    }

    // We should consider all hovering pointers here. But for now, just use the first one
    const int32_t pointerId = entry.pointerProperties[0].id;
    const PointerProperties& pointer = entry.pointerProperties[0];

    std::set<sp<WindowInfoHandle>> oldWindows;
    if (oldState != nullptr) {
        oldWindows = oldState->getWindowsWithHoveringPointer(entry.deviceId, pointerId);
        oldWindows = oldState->getWindowsWithHoveringPointer(entry.deviceId, pointer.id);
    }

    std::set<sp<WindowInfoHandle>> newWindows =
            newTouchState.getWindowsWithHoveringPointer(entry.deviceId, pointerId);
            newTouchState.getWindowsWithHoveringPointer(entry.deviceId, pointer.id);

    // If the pointer is no longer in the new window set, send HOVER_EXIT.
    for (const sp<WindowInfoHandle>& oldWindow : oldWindows) {
@@ -673,7 +681,7 @@ std::vector<TouchedWindow> getHoveringWindowsLocked(const TouchState* oldState,
            }
            touchedWindow.dispatchMode = InputTarget::DispatchMode::AS_IS;
        }
        touchedWindow.addHoveringPointer(entry.deviceId, pointerId);
        touchedWindow.addHoveringPointer(entry.deviceId, pointer);
        if (canReceiveForegroundTouches(*newWindow->getInfo())) {
            touchedWindow.targetFlags |= InputTarget::Flags::FOREGROUND;
        }
@@ -2320,7 +2328,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
        /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
        const auto [x, y] = resolveTouchedPosition(entry);
        const int32_t pointerIndex = MotionEvent::getActionIndex(action);
        const int32_t pointerId = entry.pointerProperties[pointerIndex].id;
        const PointerProperties& pointer = entry.pointerProperties[pointerIndex];
        // Outside targets should be added upon first dispatched DOWN event. That means, this should
        // be a pointer that would generate ACTION_DOWN, *and* touch should not already be down.
        const bool isStylus = isPointerFromStylus(entry, pointerIndex);
@@ -2328,7 +2336,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
                findTouchedWindowAtLocked(displayId, x, y, isStylus);

        if (isDown) {
            targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle, pointerId);
            targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle, pointer.id);
        }
        // Handle the case where we did not find a window.
        if (newTouchedWindowHandle == nullptr) {
@@ -2386,7 +2394,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(

            if (isHoverAction) {
                // The "windowHandle" is the target of this hovering pointer.
                tempTouchState.addHoveringPointerToWindow(windowHandle, entry.deviceId, pointerId);
                tempTouchState.addHoveringPointerToWindow(windowHandle, entry.deviceId, pointer);
            }

            // Set target flags.
@@ -2409,12 +2417,10 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
            // Update the temporary touch state.

            if (!isHoverAction) {
                std::bitset<MAX_POINTER_ID + 1> pointerIds;
                pointerIds.set(pointerId);
                const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN ||
                        maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN;
                tempTouchState.addOrUpdateWindow(windowHandle, InputTarget::DispatchMode::AS_IS,
                                                 targetFlags, entry.deviceId, pointerIds,
                                                 targetFlags, entry.deviceId, {pointer},
                                                 isDownOrPointerDown
                                                         ? std::make_optional(entry.eventTime)
                                                         : std::nullopt);
@@ -2437,7 +2443,7 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
                        }
                        tempTouchState.addOrUpdateWindow(wallpaper,
                                                         InputTarget::DispatchMode::AS_IS,
                                                         wallpaperFlags, entry.deviceId, pointerIds,
                                                         wallpaperFlags, entry.deviceId, {pointer},
                                                         entry.eventTime);
                    }
                }
@@ -2448,12 +2454,12 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
        // make it pilfering. This will prevent other non-spy windows from getting this pointer,
        // which is a specific behaviour that we want.
        for (TouchedWindow& touchedWindow : tempTouchState.windows) {
            if (touchedWindow.hasTouchingPointer(entry.deviceId, pointerId) &&
            if (touchedWindow.hasTouchingPointer(entry.deviceId, pointer.id) &&
                touchedWindow.hasPilferingPointers(entry.deviceId)) {
                // This window is already pilfering some pointers, and this new pointer is also
                // going to it. Therefore, take over this pointer and don't give it to anyone
                // else.
                touchedWindow.addPilferingPointer(entry.deviceId, pointerId);
                touchedWindow.addPilferingPointer(entry.deviceId, pointer.id);
            }
        }

@@ -2522,8 +2528,8 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(

                // Make a slippery exit from the old window.
                std::bitset<MAX_POINTER_ID + 1> pointerIds;
                const int32_t pointerId = entry.pointerProperties[0].id;
                pointerIds.set(pointerId);
                const PointerProperties& pointer = entry.pointerProperties[0];
                pointerIds.set(pointer.id);

                const TouchedWindow& touchedWindow =
                        tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
@@ -2553,13 +2559,13 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(

                tempTouchState.addOrUpdateWindow(newTouchedWindowHandle,
                                                 InputTarget::DispatchMode::SLIPPERY_ENTER,
                                                 targetFlags, entry.deviceId, pointerIds,
                                                 targetFlags, entry.deviceId, {pointer},
                                                 entry.eventTime);

                // Check if the wallpaper window should deliver the corresponding event.
                slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
                                   tempTouchState, entry.deviceId, pointerId, targets);
                tempTouchState.removeTouchingPointerFromWindow(entry.deviceId, pointerId,
                                   tempTouchState, entry.deviceId, pointer, targets);
                tempTouchState.removeTouchingPointerFromWindow(entry.deviceId, pointer.id,
                                                               oldTouchedWindowHandle);
            }
        }
@@ -2568,14 +2574,12 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
        if (!isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN) {
            // If no split, we suppose all touched windows should receive pointer down.
            const int32_t pointerIndex = MotionEvent::getActionIndex(action);
            for (size_t i = 0; i < tempTouchState.windows.size(); i++) {
                TouchedWindow& touchedWindow = tempTouchState.windows[i];
            std::vector<PointerProperties> touchingPointers{entry.pointerProperties[pointerIndex]};
            for (TouchedWindow& touchedWindow : tempTouchState.windows) {
                // Ignore drag window for it should just track one pointer.
                if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
                    continue;
                }
                std::bitset<MAX_POINTER_ID + 1> touchingPointers;
                touchingPointers.set(entry.pointerProperties[pointerIndex].id);
                touchedWindow.addTouchingPointers(entry.deviceId, touchingPointers);
            }
        }
@@ -2646,13 +2650,13 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(

    // Output targets from the touch state.
    for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
        std::bitset<MAX_POINTER_ID + 1> touchingPointers =
        std::vector<PointerProperties> touchingPointers =
                touchedWindow.getTouchingPointers(entry.deviceId);
        if (touchingPointers.none()) {
        if (touchingPointers.empty()) {
            continue;
        }
        addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
                                     touchedWindow.targetFlags, touchingPointers,
                                     touchedWindow.targetFlags, getPointerIds(touchingPointers),
                                     touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
    }

@@ -5481,7 +5485,7 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<

        // Erase old window.
        ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow->targetFlags;
        std::bitset<MAX_POINTER_ID + 1> pointerIds = touchedWindow->getTouchingPointers(deviceId);
        std::vector<PointerProperties> pointers = touchedWindow->getTouchingPointers(deviceId);
        sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle;
        state->removeWindowByToken(fromToken);

@@ -5493,17 +5497,17 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<
            newTargetFlags |= InputTarget::Flags::FOREGROUND;
        }
        state->addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
                                 deviceId, pointerIds, downTimeInTarget);
                                 deviceId, pointers, downTimeInTarget);

        // Store the dragging window.
        if (isDragDrop) {
            if (pointerIds.count() != 1) {
            if (pointers.size() != 1) {
                ALOGW("The drag and drop cannot be started when there is no pointer or more than 1"
                      " pointer on the window.");
                return false;
            }
            // Track the pointer id for drag window and generate the drag state.
            const size_t id = firstMarkedBit(pointerIds);
            const size_t id = pointers.begin()->id;
            mDragState = std::make_unique<DragState>(toWindowHandle, id);
        }

@@ -5520,7 +5524,7 @@ bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<

            // Check if the wallpaper window should deliver the corresponding event.
            transferWallpaperTouch(oldTargetFlags, newTargetFlags, fromWindowHandle, toWindowHandle,
                                   *state, deviceId, pointerIds);
                                   *state, deviceId, pointers);
        }
    } // release lock

@@ -5997,8 +6001,10 @@ status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) {
                                   "input channel stole pointer stream");
        options.deviceId = deviceId;
        options.displayId = displayId;
        std::bitset<MAX_POINTER_ID + 1> pointerIds = window.getTouchingPointers(deviceId);
        std::vector<PointerProperties> pointers = window.getTouchingPointers(deviceId);
        std::bitset<MAX_POINTER_ID + 1> pointerIds = getPointerIds(pointers);
        options.pointerIds = pointerIds;

        std::string canceledWindows;
        for (const TouchedWindow& w : state.windows) {
            const std::shared_ptr<InputChannel> channel =
@@ -6794,10 +6800,10 @@ void InputDispatcher::setMonitorDispatchingTimeoutForTest(std::chrono::nanosecon
void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
                                         const sp<WindowInfoHandle>& oldWindowHandle,
                                         const sp<WindowInfoHandle>& newWindowHandle,
                                         TouchState& state, int32_t deviceId, int32_t pointerId,
                                         TouchState& state, int32_t deviceId,
                                         const PointerProperties& pointerProperties,
                                         std::vector<InputTarget>& targets) const {
    std::bitset<MAX_POINTER_ID + 1> pointerIds;
    pointerIds.set(pointerId);
    std::vector<PointerProperties> pointers{pointerProperties};
    const bool oldHasWallpaper = oldWindowHandle->getInfo()->inputConfig.test(
            gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
    const bool newHasWallpaper = targetFlags.test(InputTarget::Flags::FOREGROUND) &&
@@ -6814,16 +6820,16 @@ void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFl
    if (oldWallpaper != nullptr) {
        const TouchedWindow& oldTouchedWindow = state.getTouchedWindow(oldWallpaper);
        addPointerWindowTargetLocked(oldWallpaper, InputTarget::DispatchMode::SLIPPERY_EXIT,
                                     oldTouchedWindow.targetFlags, pointerIds,
                                     oldTouchedWindow.targetFlags, getPointerIds(pointers),
                                     oldTouchedWindow.getDownTimeInTarget(deviceId), targets);
        state.removeTouchingPointerFromWindow(deviceId, pointerId, oldWallpaper);
        state.removeTouchingPointerFromWindow(deviceId, pointerProperties.id, oldWallpaper);
    }

    if (newWallpaper != nullptr) {
        state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::SLIPPERY_ENTER,
                                InputTarget::Flags::WINDOW_IS_OBSCURED |
                                        InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED,
                                deviceId, pointerIds);
                                deviceId, pointers);
    }
}

@@ -6832,7 +6838,7 @@ void InputDispatcher::transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldT
                                             const sp<WindowInfoHandle> fromWindowHandle,
                                             const sp<WindowInfoHandle> toWindowHandle,
                                             TouchState& state, int32_t deviceId,
                                             std::bitset<MAX_POINTER_ID + 1> pointerIds) {
                                             const std::vector<PointerProperties>& pointers) {
    const bool oldHasWallpaper = oldTargetFlags.test(InputTarget::Flags::FOREGROUND) &&
            fromWindowHandle->getInfo()->inputConfig.test(
                    gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
@@ -6861,7 +6867,7 @@ void InputDispatcher::transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldT
        wallpaperFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED |
                InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
        state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags,
                                deviceId, pointerIds, downTimeInTarget);
                                deviceId, pointers, downTimeInTarget);
        std::shared_ptr<Connection> wallpaperConnection =
                getConnectionLocked(newWallpaper->getToken());
        if (wallpaperConnection != nullptr) {
+3 −2
Original line number Diff line number Diff line
@@ -690,14 +690,15 @@ private:
    void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
                            const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
                            const sp<android::gui::WindowInfoHandle>& newWindowHandle,
                            TouchState& state, int32_t deviceId, int32_t pointerId,
                            TouchState& state, int32_t deviceId,
                            const PointerProperties& pointerProperties,
                            std::vector<InputTarget>& targets) const REQUIRES(mLock);
    void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
                                ftl::Flags<InputTarget::Flags> newTargetFlags,
                                const sp<android::gui::WindowInfoHandle> fromWindowHandle,
                                const sp<android::gui::WindowInfoHandle> toWindowHandle,
                                TouchState& state, int32_t deviceId,
                                std::bitset<MAX_POINTER_ID + 1> pointerIds) REQUIRES(mLock);
                                const std::vector<PointerProperties>& pointers) REQUIRES(mLock);

    sp<android::gui::WindowInfoHandle> findWallpaperWindowBelow(
            const sp<android::gui::WindowInfoHandle>& windowHandle) const REQUIRES(mLock);
+7 −7
Original line number Diff line number Diff line
@@ -73,9 +73,9 @@ void TouchState::clearWindowsWithoutPointers() {
void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
                                   InputTarget::DispatchMode dispatchMode,
                                   ftl::Flags<InputTarget::Flags> targetFlags, DeviceId deviceId,
                                   std::bitset<MAX_POINTER_ID + 1> touchingPointerIds,
                                   const std::vector<PointerProperties>& touchingPointers,
                                   std::optional<nsecs_t> firstDownTimeInTarget) {
    if (touchingPointerIds.none()) {
    if (touchingPointers.empty()) {
        LOG(FATAL) << __func__ << "No pointers specified for " << windowHandle->getName();
        return;
    }
@@ -91,7 +91,7 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
            // For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
            // downTime set initially. Need to update existing window when a pointer is down for the
            // window.
            touchedWindow.addTouchingPointers(deviceId, touchingPointerIds);
            touchedWindow.addTouchingPointers(deviceId, touchingPointers);
            if (firstDownTimeInTarget) {
                touchedWindow.trySetDownTimeInTarget(deviceId, *firstDownTimeInTarget);
            }
@@ -102,7 +102,7 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
    touchedWindow.windowHandle = windowHandle;
    touchedWindow.dispatchMode = dispatchMode;
    touchedWindow.targetFlags = targetFlags;
    touchedWindow.addTouchingPointers(deviceId, touchingPointerIds);
    touchedWindow.addTouchingPointers(deviceId, touchingPointers);
    if (firstDownTimeInTarget) {
        touchedWindow.trySetDownTimeInTarget(deviceId, *firstDownTimeInTarget);
    }
@@ -110,17 +110,17 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
}

void TouchState::addHoveringPointerToWindow(const sp<WindowInfoHandle>& windowHandle,
                                            DeviceId deviceId, int32_t hoveringPointerId) {
                                            DeviceId deviceId, const PointerProperties& pointer) {
    for (TouchedWindow& touchedWindow : windows) {
        if (touchedWindow.windowHandle == windowHandle) {
            touchedWindow.addHoveringPointer(deviceId, hoveringPointerId);
            touchedWindow.addHoveringPointer(deviceId, pointer);
            return;
        }
    }

    TouchedWindow touchedWindow;
    touchedWindow.windowHandle = windowHandle;
    touchedWindow.addHoveringPointer(deviceId, hoveringPointerId);
    touchedWindow.addHoveringPointer(deviceId, pointer);
    windows.push_back(touchedWindow);
}

Loading