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

Commit 24a00a93 authored by Arpit Singh's avatar Arpit Singh
Browse files

[15/n Dispatcher refactor] Remove TouchState from setInputWindows

In this CL we remove direct access to touchState internals from
setInputWindows method.

Bug: 367661487
Bug: 245989146
Test: atest inputflinger_tests
Flag: EXEMPT refactor
Change-Id: Ibdd09f429e2f6d7c365a2b9bd295df21c193910a
parent b9e6e59b
Loading
Loading
Loading
Loading
+99 −63
Original line number Diff line number Diff line
@@ -5453,86 +5453,122 @@ void InputDispatcher::setInputWindowsLocked(
        onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle);
    }

    if (const auto& it = mTouchStates.mTouchStatesByDisplay.find(displayId);
        it != mTouchStates.mTouchStatesByDisplay.end()) {
    CancelationOptions pointerCancellationOptions(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
                                                  "touched window was removed",
                                                  traceContext.getTracker());
    CancelationOptions hoverCancellationOptions(CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
                                                "WindowInfo changed", traceContext.getTracker());
    const std::list<DispatcherTouchState::CancellationArgs> cancellations =
            mTouchStates.updateFromWindowInfo(displayId, mWindowInfos);
    for (const auto& cancellationArgs : cancellations) {
        switch (cancellationArgs.mode) {
            case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
                pointerCancellationOptions.deviceId = cancellationArgs.deviceId;
                synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle,
                                                           pointerCancellationOptions);
                break;
            case CancelationOptions::Mode::CANCEL_HOVER_EVENTS:
                hoverCancellationOptions.deviceId = cancellationArgs.deviceId;
                synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle,
                                                           hoverCancellationOptions);
                break;
            default:
                LOG_ALWAYS_FATAL("Unexpected cancellation Mode");
        }
    }

    // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
    // could just clear the state here.
    if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
        std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
                windowHandles.end()) {
        ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
        sendDropWindowCommandLocked(nullptr, 0, 0);
        mDragState.reset();
    }

    // Release information for windows that are no longer present.
    // This ensures that unused input channels are released promptly.
    // Otherwise, they might stick around until the window handle is destroyed
    // which might not happen until the next GC.
    for (const sp<WindowInfoHandle>& oldWindowHandle : oldWindowHandles) {
        if (!mWindowInfos.isWindowPresent(oldWindowHandle)) {
            if (DEBUG_FOCUS) {
                ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
            }
            oldWindowHandle->releaseChannel();
        }
    }
}

std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
InputDispatcher::DispatcherTouchState::updateFromWindowInfo(
        ui::LogicalDisplayId displayId, const DispatcherWindowInfo& windowInfos) {
    std::list<CancellationArgs> cancellations;
    if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
        TouchState& state = it->second;
        for (size_t i = 0; i < state.windows.size();) {
            TouchedWindow& touchedWindow = state.windows[i];
            if (mWindowInfos.isWindowPresent(touchedWindow.windowHandle)) {
                i++;
        cancellations = eraseRemovedWindowsFromWindowInfo(state, displayId, windowInfos);
        cancellations.splice(cancellations.end(),
                             updateHoveringStateFromWindowInfo(state, displayId, windowInfos));
    }
    return cancellations;
}

std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
InputDispatcher::DispatcherTouchState::eraseRemovedWindowsFromWindowInfo(
        TouchState& state, ui::LogicalDisplayId displayId,
        const DispatcherWindowInfo& windowInfos) {
    std::list<CancellationArgs> cancellations;
    for (auto it = state.windows.begin(); it != state.windows.end();) {
        TouchedWindow& touchedWindow = *it;
        if (windowInfos.isWindowPresent(touchedWindow.windowHandle)) {
            it++;
            continue;
        }
        LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
                  << " in display %" << displayId;
            CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
                                       "touched window was removed", traceContext.getTracker());
            synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
            // Since we are about to drop the touch, cancel the events for the wallpaper as
            // well.
        cancellations.emplace_back(touchedWindow.windowHandle,
                                   CancelationOptions::Mode::CANCEL_POINTER_EVENTS, std::nullopt);
        // Since we are about to drop the touch, cancel the events for the wallpaper as well.
        if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
            touchedWindow.windowHandle->getInfo()->inputConfig.test(
                    gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
            for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
                if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
                        options.deviceId = deviceId;
                        synthesizeCancelationEventsForWindowLocked(ww, options);
                    cancellations.emplace_back(ww, CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
                                               deviceId);
                }
            }
        }
            state.windows.erase(state.windows.begin() + i);
        }

        // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
        // could just clear the state here.
        if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
            std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
                    windowHandles.end()) {
            ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
            sendDropWindowCommandLocked(nullptr, 0, 0);
            mDragState.reset();
        it = state.windows.erase(it);
    }
    return cancellations;
}

std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
InputDispatcher::DispatcherTouchState::updateHoveringStateFromWindowInfo(
        TouchState& state, ui::LogicalDisplayId displayId,
        const DispatcherWindowInfo& windowInfos) {
    std::list<CancellationArgs> cancellations;
    // Check if the hovering should stop because the window is no longer eligible to receive it
    // (for example, if the touchable region changed)
    if (const auto& it = mTouchStates.mTouchStatesByDisplay.find(displayId);
        it != mTouchStates.mTouchStatesByDisplay.end()) {
        TouchState& state = it->second;
    ui::Transform displayTransform = windowInfos.getDisplayTransform(displayId);
    for (TouchedWindow& touchedWindow : state.windows) {
        std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf(
                    [this, displayId, &touchedWindow](const PointerProperties& properties, float x,
                                                      float y) REQUIRES(mLock) {
                [&](const PointerProperties& properties, float x, float y) {
                    const bool isStylus = properties.toolType == ToolType::STYLUS;
                        const ui::Transform displayTransform =
                                mWindowInfos.getDisplayTransform(displayId);
                    const bool stillAcceptsTouch =
                                windowAcceptsTouchAt(*touchedWindow.windowHandle->getInfo(),
                                                     displayId, x, y, isStylus, displayTransform);
                            windowAcceptsTouchAt(*touchedWindow.windowHandle->getInfo(), displayId,
                                                 x, y, isStylus, displayTransform);
                    return !stillAcceptsTouch;
                });

        for (DeviceId deviceId : erasedDevices) {
                CancelationOptions options(CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
                                           "WindowInfo changed",
                                           traceContext.getTracker());
                options.deviceId = deviceId;
                synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
            }
        }
    }

    // Release information for windows that are no longer present.
    // This ensures that unused input channels are released promptly.
    // Otherwise, they might stick around until the window handle is destroyed
    // which might not happen until the next GC.
    for (const sp<WindowInfoHandle>& oldWindowHandle : oldWindowHandles) {
        if (!mWindowInfos.isWindowPresent(oldWindowHandle)) {
            if (DEBUG_FOCUS) {
                ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
            }
            oldWindowHandle->releaseChannel();
            cancellations.emplace_back(touchedWindow.windowHandle,
                                       CancelationOptions::Mode::CANCEL_HOVER_EVENTS, deviceId);
        }
    }
    return cancellations;
}

void InputDispatcher::setFocusedApplication(
+22 −4
Original line number Diff line number Diff line
@@ -352,6 +352,12 @@ private:

    class DispatcherTouchState {
    public:
        struct CancellationArgs {
            const sp<gui::WindowInfoHandle> windowHandle;
            CancelationOptions::Mode mode;
            std::optional<DeviceId> deviceId;
        };

        static void addPointerWindowTarget(const sp<android::gui::WindowInfoHandle>& windowHandle,
                                           InputTarget::DispatchMode dispatchMode,
                                           ftl::Flags<InputTarget::Flags> targetFlags,
@@ -380,6 +386,11 @@ private:

        std::string dump() const;

        // Updates the touchState for display from WindowInfo,
        // return vector of CancellationArgs for every cancelled touch
        std::list<CancellationArgs> updateFromWindowInfo(ui::LogicalDisplayId displayId,
                                                         const DispatcherWindowInfo& windowInfos);

        void removeAllPointersForDevice(DeviceId deviceId);

        void clear();
@@ -387,11 +398,18 @@ private:
        std::unordered_map<ui::LogicalDisplayId, TouchState> mTouchStatesByDisplay;

    private:
        static std::list<CancellationArgs> eraseRemovedWindowsFromWindowInfo(
                TouchState& state, ui::LogicalDisplayId displayId,
                const DispatcherWindowInfo& windowInfos);

        static std::list<CancellationArgs> updateHoveringStateFromWindowInfo(
                TouchState& state, ui::LogicalDisplayId displayId,
                const DispatcherWindowInfo& windowInfos);

        static std::vector<InputTarget> findOutsideTargets(
                ui::LogicalDisplayId displayId,
                const sp<android::gui::WindowInfoHandle>& touchedWindow, int32_t pointerId,
                const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos,
                std::function<void()> dump);
                ui::LogicalDisplayId displayId, const sp<gui::WindowInfoHandle>& touchedWindow,
                int32_t pointerId, const ConnectionManager& connections,
                const DispatcherWindowInfo& windowInfos, std::function<void()> dump);

        /**
         * Slip the wallpaper touch if necessary.