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

Commit 6b71b637 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Do not drop stale events for gestures in progress

Before this CL, stale events would get dropped by the dispatcher and
cause inconsistent event streams to be sent further down the pipeline.
This would cause a crash.

In this CL, we prevent dropping stale events when the gesture is
currently in progress. This ensures that only events that start a new
gesture could be dropped due to being stale.

Test: TEST=inputflinger_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST
Bug: 308153460
Change-Id: I8348dc9e175214dab3f68f33ad52a117637c2f9a
parent d6a6f38c
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -1090,8 +1090,17 @@ 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 = mTouchStatesByDisplay.find(motionEntry->displayId);
                if (touchStateIt != mTouchStatesByDisplay.end()) {
                    const TouchState& touchState = touchStateIt->second;
                    if (!touchState.hasTouchingPointers(motionEntry->deviceId) &&
                        !touchState.hasHoveringPointers(motionEntry->deviceId)) {
                        dropReason = DropReason::STALE;
                    }
                }
            }
            if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
                dropReason = DropReason::BLOCKED;
            }
+38 −0
Original line number Diff line number Diff line
@@ -3412,6 +3412,44 @@ TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
    window->assertNoEvents();
}
/**
 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
 * rejected. But since we already have an ongoing gesture, this event should be processed.
 * This prevents inconsistent events being handled inside the dispatcher.
 */
TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
    window->setFrame(Rect(0, 0, 200, 200));
    mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
    // Start hovering with stylus
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
                                      .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
                                      .build());
    window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
    NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
                                         .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
                                         .build();
    // Make this 'hoverExit' event stale
    mFakePolicy->setStaleEventTimeout(100ms);
    std::this_thread::sleep_for(100ms);
    // It shouldn't be dropped by the dispatcher, even though it's stale.
    mDispatcher->notifyMotion(hoverExit);
    window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
    // Stylus starts hovering again! There should be no crash.
    mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
                                      .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
                                      .build());
    window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
}
/**
 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse