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

Commit b9e6e59b authored by Arpit Singh's avatar Arpit Singh
Browse files

[14/n Dispatcher refactor] Move TouchState methods

In this CL we move or create following TouchState related methods to the
TouchState class:
1. clear
2. isPointerInWindow
3. hasTouchingOrHoveringPointers
4. removeAllPointersForDevice
5. dump

This CL also updates InputDispatcherUserActivityPokeTests to use current
time to inject events, to avoid them being dropped as stale.

Bug: 367661487
Bug: 245989146
Test: atest inputflinger_tests
Flag: EXEMPT refactor
Change-Id: I624700a78471a85a1e97c06b170137ee4e6ddf82
parent 403a3d75
Loading
Loading
Loading
Loading
+64 −48
Original line number Diff line number Diff line
@@ -1267,16 +1267,11 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t& nextWakeupTime) {
            if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
                // The event is stale. However, only drop stale events if there isn't an ongoing
                // gesture. That would allow us to complete the processing of the current stroke.
                const auto touchStateIt =
                        mTouchStates.mTouchStatesByDisplay.find(motionEntry->displayId);
                if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) {
                    const TouchState& touchState = touchStateIt->second;
                    if (!touchState.hasTouchingPointers(motionEntry->deviceId) &&
                        !touchState.hasHoveringPointers(motionEntry->deviceId)) {
                if (!mTouchStates.hasTouchingOrHoveringPointers(motionEntry->displayId,
                                                                motionEntry->deviceId)) {
                    dropReason = DropReason::STALE;
                }
            }
            }
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
                if (!isFromSource(motionEntry->source, AINPUT_SOURCE_CLASS_POINTER)) {
                    // Only drop events that are focus-dispatched.
@@ -1716,9 +1711,7 @@ bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime,
    synthesizeCancelationEventsForAllConnectionsLocked(options);

    // Remove all active pointers from this device
    for (auto& [_, touchState] : mTouchStates.mTouchStatesByDisplay) {
        touchState.removeAllPointersForDevice(entry.deviceId);
    }
    mTouchStates.removeAllPointersForDevice(entry.deviceId);
    return true;
}

@@ -4581,15 +4574,10 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) {
        if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
            // Set the flag anyway if we already have an ongoing gesture. That would allow us to
            // complete the processing of the current stroke.
            const auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(args.displayId);
            if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) {
                const TouchState& touchState = touchStateIt->second;
                if (touchState.hasTouchingPointers(args.deviceId) ||
                    touchState.hasHoveringPointers(args.deviceId)) {
            if (mTouchStates.hasTouchingOrHoveringPointers(args.displayId, args.deviceId)) {
                policyFlags |= POLICY_FLAG_PASS_TO_USER;
            }
        }
        }

        if (shouldSendMotionToInputFilterLocked(args)) {
            ui::Transform displayTransform = mWindowInfos.getDisplayTransform(args.displayId);
@@ -4893,15 +4881,10 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* ev
            if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
                // Set the flag anyway if we already have an ongoing motion gesture. That
                // would allow us to complete the processing of the current stroke.
                const auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(displayId);
                if (touchStateIt != mTouchStates.mTouchStatesByDisplay.end()) {
                    const TouchState& touchState = touchStateIt->second;
                    if (touchState.hasTouchingPointers(resolvedDeviceId) ||
                        touchState.hasHoveringPointers(resolvedDeviceId)) {
                if (mTouchStates.hasTouchingOrHoveringPointers(displayId, resolvedDeviceId)) {
                    policyFlags |= POLICY_FLAG_PASS_TO_USER;
                }
            }
            }

            const nsecs_t* sampleEventTimes = motionEvent.getSampleEventTimes();
            const size_t pointerCount = motionEvent.getPointerCount();
@@ -5978,7 +5961,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
    resetNoFocusedWindowTimeoutLocked();

    mAnrTracker.clear();
    mTouchStates.mTouchStatesByDisplay.clear();
    mTouchStates.clear();
}

void InputDispatcher::logDispatchStateLocked() const {
@@ -6036,15 +6019,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const {
    dump += mFocusResolver.dump();
    dump += dumpPointerCaptureStateLocked();

    if (!mTouchStates.mTouchStatesByDisplay.empty()) {
        dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
        for (const auto& [displayId, state] : mTouchStates.mTouchStatesByDisplay) {
            std::string touchStateDump = addLinePrefix(state.dump(), INDENT2);
            dump += INDENT2 + displayId.toString() + " : " + touchStateDump;
        }
    } else {
        dump += INDENT "TouchStates: <no displays touched>\n";
    }
    dump += addLinePrefix(mTouchStates.dump(), INDENT);

    if (mDragState) {
        dump += StringPrintf(INDENT "DragState:\n");
@@ -7093,7 +7068,7 @@ void InputDispatcher::cancelCurrentTouch() {
                                   "cancel current touch", traceContext.getTracker());
        synthesizeCancelationEventsForAllConnectionsLocked(options);

        mTouchStates.mTouchStatesByDisplay.clear();
        mTouchStates.clear();
    }
    // Wake up poll loop since there might be work to do.
    mLooper->wake();
@@ -7228,18 +7203,7 @@ bool InputDispatcher::isPointerInWindow(const sp<android::IBinder>& token,
                                        ui::LogicalDisplayId displayId, DeviceId deviceId,
                                        int32_t pointerId) {
    std::scoped_lock _l(mLock);
    auto touchStateIt = mTouchStates.mTouchStatesByDisplay.find(displayId);
    if (touchStateIt == mTouchStates.mTouchStatesByDisplay.end()) {
        return false;
    }
    for (const TouchedWindow& window : touchStateIt->second.windows) {
        if (window.windowHandle->getToken() == token &&
            (window.hasTouchingPointer(deviceId, pointerId) ||
             window.hasHoveringPointer(deviceId, pointerId))) {
            return true;
        }
    }
    return false;
    return mTouchStates.isPointerInWindow(token, displayId, deviceId, pointerId);
}

void InputDispatcher::setInputMethodConnectionIsActive(bool isActive) {
@@ -7403,4 +7367,56 @@ ftl::Flags<InputTarget::Flags> InputDispatcher::DispatcherTouchState::getTargetF
    return targetFlags;
}

bool InputDispatcher::DispatcherTouchState::hasTouchingOrHoveringPointers(
        ui::LogicalDisplayId displayId, int32_t deviceId) const {
    const auto touchStateIt = mTouchStatesByDisplay.find(displayId);
    if (touchStateIt == mTouchStatesByDisplay.end()) {
        return false;
    }
    return touchStateIt->second.hasTouchingPointers(deviceId) ||
            touchStateIt->second.hasHoveringPointers(deviceId);
}

bool InputDispatcher::DispatcherTouchState::isPointerInWindow(const sp<android::IBinder>& token,
                                                              ui::LogicalDisplayId displayId,
                                                              android::DeviceId deviceId,
                                                              int32_t pointerId) const {
    const auto touchStateIt = mTouchStatesByDisplay.find(displayId);
    if (touchStateIt == mTouchStatesByDisplay.end()) {
        return false;
    }
    for (const TouchedWindow& window : touchStateIt->second.windows) {
        if (window.windowHandle->getToken() == token &&
            (window.hasTouchingPointer(deviceId, pointerId) ||
             window.hasHoveringPointer(deviceId, pointerId))) {
            return true;
        }
    }
    return false;
}

std::string InputDispatcher::DispatcherTouchState::dump() const {
    std::string dump;
    if (!mTouchStatesByDisplay.empty()) {
        dump += StringPrintf("TouchStatesByDisplay:\n");
        for (const auto& [displayId, state] : mTouchStatesByDisplay) {
            std::string touchStateDump = addLinePrefix(state.dump(), INDENT);
            dump += INDENT + displayId.toString() + " : " + touchStateDump;
        }
    } else {
        dump += "TouchStates: <no displays touched>\n";
    }
    return dump;
}

void InputDispatcher::DispatcherTouchState::removeAllPointersForDevice(android::DeviceId deviceId) {
    for (auto& [_, touchState] : mTouchStatesByDisplay) {
        touchState.removeAllPointersForDevice(deviceId);
    }
}

void InputDispatcher::DispatcherTouchState::clear() {
    mTouchStatesByDisplay.clear();
}

} // namespace android::inputdispatcher
+11 −0
Original line number Diff line number Diff line
@@ -373,6 +373,17 @@ private:
        sp<android::gui::WindowInfoHandle> findTouchedForegroundWindow(
                ui::LogicalDisplayId displayId) const;

        bool hasTouchingOrHoveringPointers(ui::LogicalDisplayId displayId, int32_t deviceId) const;

        bool isPointerInWindow(const sp<android::IBinder>& token, ui::LogicalDisplayId displayId,
                               DeviceId deviceId, int32_t pointerId) const;

        std::string dump() const;

        void removeAllPointersForDevice(DeviceId deviceId);

        void clear();

        std::unordered_map<ui::LogicalDisplayId, TouchState> mTouchStatesByDisplay;

    private:
+30 −20
Original line number Diff line number Diff line
@@ -9959,57 +9959,63 @@ TEST_F_WITH_FLAGS(
        InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
                                            rate_limit_user_activity_poke_in_dispatcher))) {
    // Use current time otherwise events may be dropped due to being stale.
    const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
    mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
    // First event of type TOUCH. Should poke.
    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                           milliseconds_to_nanoseconds(50));
                           currentTime + milliseconds_to_nanoseconds(50));
    mFakePolicy->assertUserActivityPoked(
            {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
            {{currentTime + milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
              ui::LogicalDisplayId::DEFAULT}});
    // 80ns > 50ns has passed since previous TOUCH event. Should poke.
    notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                           milliseconds_to_nanoseconds(130));
                           currentTime + milliseconds_to_nanoseconds(130));
    mFakePolicy->assertUserActivityPoked(
            {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
            {{currentTime + milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
              ui::LogicalDisplayId::DEFAULT}});
    // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
    notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
                           ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
                           ui::LogicalDisplayId::DEFAULT,
                           currentTime + milliseconds_to_nanoseconds(135));
    mFakePolicy->assertUserActivityPoked(
            {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
            {{currentTime + milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
              ui::LogicalDisplayId::DEFAULT}});
    // Within 50ns of previous TOUCH event. Should NOT poke.
    notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                           milliseconds_to_nanoseconds(140));
                           currentTime + milliseconds_to_nanoseconds(140));
    mFakePolicy->assertUserActivityNotPoked();
    // Within 50ns of previous OTHER event. Should NOT poke.
    notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
                           ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
                           ui::LogicalDisplayId::DEFAULT,
                           currentTime + milliseconds_to_nanoseconds(150));
    mFakePolicy->assertUserActivityNotPoked();
    // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
    // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
                           milliseconds_to_nanoseconds(160));
                           currentTime + milliseconds_to_nanoseconds(160));
    mFakePolicy->assertUserActivityNotPoked();
    // 65ns > 50ns has passed since previous OTHER event. Should poke.
    notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
                           ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
                           ui::LogicalDisplayId::DEFAULT,
                           currentTime + milliseconds_to_nanoseconds(200));
    mFakePolicy->assertUserActivityPoked(
            {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
            {{currentTime + milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
              ui::LogicalDisplayId::DEFAULT}});
    // 170ns > 50ns has passed since previous TOUCH event. Should poke.
    notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
                           milliseconds_to_nanoseconds(300));
                           currentTime + milliseconds_to_nanoseconds(300));
    mFakePolicy->assertUserActivityPoked(
            {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
            {{currentTime + milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
              ui::LogicalDisplayId::DEFAULT}});
    // Assert that there's no more user activity poke event.
@@ -10020,20 +10026,22 @@ TEST_F_WITH_FLAGS(
        InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
                                            rate_limit_user_activity_poke_in_dispatcher))) {
    // Use current time otherwise events may be dropped due to being stale.
    const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                           milliseconds_to_nanoseconds(200));
                           currentTime + milliseconds_to_nanoseconds(200));
    mFakePolicy->assertUserActivityPoked(
            {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
            {{currentTime + milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
              ui::LogicalDisplayId::DEFAULT}});
    notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                           milliseconds_to_nanoseconds(280));
                           currentTime + milliseconds_to_nanoseconds(280));
    mFakePolicy->assertUserActivityNotPoked();
    notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                           milliseconds_to_nanoseconds(340));
                           currentTime + milliseconds_to_nanoseconds(340));
    mFakePolicy->assertUserActivityPoked(
            {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
            {{currentTime + milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
              ui::LogicalDisplayId::DEFAULT}});
}
@@ -10041,14 +10049,16 @@ TEST_F_WITH_FLAGS(
        InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
                                            rate_limit_user_activity_poke_in_dispatcher))) {
    // Use current time otherwise events may be dropped due to being stale.
    const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
    mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
    notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                           20);
                           currentTime + 20);
    mFakePolicy->assertUserActivityPoked();
    notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
                           30);
                           currentTime + 30);
    mFakePolicy->assertUserActivityPoked();
}