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

Commit 4b09c1f9 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

InputDispatcher: Use a single dispatch mode per target

Previously, the concept of dispatch mode was intertwined with
InputTarget flags. Since dispatch modes were part of the flags, it was
possible for an InputTarget of one event to be receive the event through
more than one dispatch mode.

Right now, there should be no use case for a target to have one event
dispatched through multiple dispatch modes. Even for the case in which
an ACTION_DOWN for a hovering pointer should generate both HOVER_EXIT
and ACTION_DOWN, this process is handled by using two InputTargets
instead of reusing one target to send both events.

We pull out the dispatch modes from the target flags into its own enum.
Dispatch modes are no longer flags, so each input target will have
exactly one dispatch mode. If an event should be dispatched via multiple
modes to the same window, mutiple InputTargets should be used.

Bug: 210460522
Test: atest inpuflinger_tests
Change-Id: I6c3f082ad48e312db6fcdeb7ef7c158d9dc53c2d
parent 4cd9cb2c
Loading
Loading
Loading
Loading
+94 −117

File changed.

Preview size limit exceeded, changes collapsed.

+7 −7
Original line number Diff line number Diff line
@@ -528,13 +528,15 @@ private:

    std::optional<InputTarget> createInputTargetLocked(
            const sp<android::gui::WindowInfoHandle>& windowHandle,
            ftl::Flags<InputTarget::Flags> targetFlags,
            InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
            std::optional<nsecs_t> firstDownTimeInTarget) const REQUIRES(mLock);
    void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
                               InputTarget::DispatchMode dispatchMode,
                               ftl::Flags<InputTarget::Flags> targetFlags,
                               std::optional<nsecs_t> firstDownTimeInTarget,
                               std::vector<InputTarget>& inputTargets) const REQUIRES(mLock);
    void addPointerWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
                                      InputTarget::DispatchMode dispatchMode,
                                      ftl::Flags<InputTarget::Flags> targetFlags,
                                      std::bitset<MAX_POINTER_ID + 1> pointerIds,
                                      std::optional<nsecs_t> firstDownTimeInTarget,
@@ -580,14 +582,12 @@ private:
                                    const std::shared_ptr<Connection>& connection,
                                    std::shared_ptr<const EventEntry>,
                                    const InputTarget& inputTarget) REQUIRES(mLock);
    void enqueueDispatchEntriesLocked(nsecs_t currentTime,
                                      const std::shared_ptr<Connection>& connection,
                                      std::shared_ptr<const EventEntry>,
                                      const InputTarget& inputTarget) REQUIRES(mLock);
    void enqueueDispatchEntryAndStartDispatchCycleLocked(
            nsecs_t currentTime, const std::shared_ptr<Connection>& connection,
            std::shared_ptr<const EventEntry>, const InputTarget& inputTarget) REQUIRES(mLock);
    void enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
                                    std::shared_ptr<const EventEntry>,
                                    const InputTarget& inputTarget,
                                    ftl::Flags<InputTarget::Flags> dispatchMode) REQUIRES(mLock);
                                    const InputTarget& inputTarget) REQUIRES(mLock);
    status_t publishMotionEvent(Connection& connection, DispatchEntry& dispatchEntry) const;
    void startDispatchCycleLocked(nsecs_t currentTime,
                                  const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ std::ostream& operator<<(std::ostream& out, const InputTarget& target) {
    } else {
        out << "<null>";
    }
    out << ", dispatchMode=" << ftl::enum_string(target.dispatchMode).c_str();
    out << ", targetFlags=" << target.flags.string();
    out << ", pointers=" << target.getPointerInfoString();
    out << "}";
+17 −21
Original line number Diff line number Diff line
@@ -51,53 +51,49 @@ struct InputTarget {
         * the same UID from watching all touches. */
        ZERO_COORDS = 1 << 3,

        /* This flag indicates that the target of a MotionEvent is partly or wholly
         * obscured by another visible window above it.  The motion event should be
         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
        WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
    };

    enum class DispatchMode {
        /* This flag indicates that the event should be sent as is.
         * Should always be set unless the event is to be transmuted. */
        DISPATCH_AS_IS = 1 << 8,

        AS_IS,
        /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
         * of the area of this target and so should instead be delivered as an
         * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
        DISPATCH_AS_OUTSIDE = 1 << 9,

        OUTSIDE,
        /* This flag indicates that a hover sequence is starting in the given window.
         * The event is transmuted into ACTION_HOVER_ENTER. */
        DISPATCH_AS_HOVER_ENTER = 1 << 10,

        HOVER_ENTER,
        /* This flag indicates that a hover event happened outside of a window which handled
         * previous hover events, signifying the end of the current hover sequence for that
         * window.
         * The event is transmuted into ACTION_HOVER_ENTER. */
        DISPATCH_AS_HOVER_EXIT = 1 << 11,

        HOVER_EXIT,
        /* This flag indicates that the event should be canceled.
         * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
         * outside of a window. */
        DISPATCH_AS_SLIPPERY_EXIT = 1 << 12,

        SLIPPERY_EXIT,
        /* This flag indicates that the event should be dispatched as an initial down.
         * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
         * into a new window. */
        DISPATCH_AS_SLIPPERY_ENTER = 1 << 13,
        SLIPPERY_ENTER,

        /* This flag indicates that the target of a MotionEvent is partly or wholly
         * obscured by another visible window above it.  The motion event should be
         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
        WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
        ftl_last = SLIPPERY_ENTER,
    };

    /* Mask for all dispatch modes. */
    static constexpr const ftl::Flags<InputTarget::Flags> DISPATCH_MASK =
            ftl::Flags<InputTarget::Flags>() | Flags::DISPATCH_AS_IS | Flags::DISPATCH_AS_OUTSIDE |
            Flags::DISPATCH_AS_HOVER_ENTER | Flags::DISPATCH_AS_HOVER_EXIT |
            Flags::DISPATCH_AS_SLIPPERY_EXIT | Flags::DISPATCH_AS_SLIPPERY_ENTER;

    // The input channel to be targeted.
    std::shared_ptr<InputChannel> inputChannel;

    // Flags for the input target.
    ftl::Flags<Flags> flags;

    // The dispatch mode that should be used for this target.
    DispatchMode dispatchMode = DispatchMode::AS_IS;

    // Scaling factor to apply to MotionEvent as it is delivered.
    // (ignored for KeyEvents)
    float globalScaleFactor = 1.0f;
+3 −17
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ 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,
                                   std::optional<nsecs_t> firstDownTimeInTarget) {
@@ -85,10 +86,8 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
        // An alternative design choice here would have been to compare here by token, but to
        // store per-pointer transform.
        if (touchedWindow.windowHandle == windowHandle) {
            touchedWindow.dispatchMode = dispatchMode;
            touchedWindow.targetFlags |= targetFlags;
            if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
                touchedWindow.targetFlags.clear(InputTarget::Flags::DISPATCH_AS_IS);
            }
            // 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.
@@ -101,6 +100,7 @@ void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
    }
    TouchedWindow touchedWindow;
    touchedWindow.windowHandle = windowHandle;
    touchedWindow.dispatchMode = dispatchMode;
    touchedWindow.targetFlags = targetFlags;
    touchedWindow.addTouchingPointers(deviceId, touchingPointerIds);
    if (firstDownTimeInTarget) {
@@ -133,20 +133,6 @@ void TouchState::removeWindowByToken(const sp<IBinder>& token) {
    }
}

void TouchState::filterNonAsIsTouchWindows() {
    for (size_t i = 0; i < windows.size();) {
        TouchedWindow& window = windows[i];
        if (window.targetFlags.any(InputTarget::Flags::DISPATCH_AS_IS |
                                   InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
            window.targetFlags.clear(InputTarget::DISPATCH_MASK);
            window.targetFlags |= InputTarget::Flags::DISPATCH_AS_IS;
            i += 1;
        } else {
            windows.erase(windows.begin() + i);
        }
    }
}

void TouchState::cancelPointersForWindowsExcept(DeviceId deviceId,
                                                std::bitset<MAX_POINTER_ID + 1> pointerIds,
                                                const sp<IBinder>& token) {
Loading