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

Commit 7f1efed1 authored by Paul Ramirez's avatar Paul Ramirez
Browse files

Add check to not resample when resample time equals motion event time

Included SampleTimeEqualsEventTime from TouchResampling_test.cpp into
InputConsumerResampling_test.cpp, and added the missing logic in
LegacyResampler to pass the test.

Bug: 297226446
Flag: EXEMPT refactor
Test: TEST=libinput_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST --gtest_filter="InputConsumerResamplingTest*"
Change-Id: I8ff9a263ea79eed1b814d2b1ce0b7efb5ade584e
parent 5d59a429
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -65,7 +65,8 @@ public:
     * extrapolation takes place and `resampleTime` is too far in the future. If `futureSample` is
     * not null, interpolation will occur. If `futureSample` is null and there is enough historical
     * data, LegacyResampler will extrapolate. Otherwise, no resampling takes place and
     * `motionEvent` is unmodified.
     * `motionEvent` is unmodified. Furthermore, motionEvent is not resampled if resampleTime equals
     * the last sample eventTime of motionEvent.
     */
    void resampleMotionEvent(std::chrono::nanoseconds frameTime, MotionEvent& motionEvent,
                             const InputMessage* futureSample) override;
+5 −0
Original line number Diff line number Diff line
@@ -249,6 +249,11 @@ void LegacyResampler::resampleMotionEvent(nanoseconds frameTime, MotionEvent& mo
                                          const InputMessage* futureSample) {
    const nanoseconds resampleTime = frameTime - RESAMPLE_LATENCY;

    if (resampleTime.count() == motionEvent.getEventTime()) {
        LOG_IF(INFO, debugResampling()) << "Not resampled. Resample time equals motion event time.";
        return;
    }

    updateLatestSamples(motionEvent);

    const std::optional<Sample> sample = (futureSample != nullptr)
+44 −7
Original line number Diff line number Diff line

/*
 * Copyright (C) 2024 The Android Open Source Project
 *
@@ -193,7 +192,7 @@ void InputConsumerResamplingTest::assertReceivedMotionEvent(
 * last two real events, which would put this time at: 20 ms + (20 ms - 10 ms) / 2 = 25 ms.
 */
TEST_F(InputConsumerResamplingTest, EventIsResampled) {
    // Initial ACTION_DOWN should be separate, because the first consume event will only return
    // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an
    // InputEvent with a single action.
    mClientTestChannel->enqueueMessage(nextPointerMessage(
            {0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN}));
@@ -234,7 +233,7 @@ TEST_F(InputConsumerResamplingTest, EventIsResampled) {
 * have these hardcoded.
 */
TEST_F(InputConsumerResamplingTest, EventIsResampledWithDifferentId) {
    // Initial ACTION_DOWN should be separate, because the first consume event will only return
    // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an
    // InputEvent with a single action.
    mClientTestChannel->enqueueMessage(nextPointerMessage(
            {0ms, {Pointer{.id = 1, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN}));
@@ -274,7 +273,7 @@ TEST_F(InputConsumerResamplingTest, EventIsResampledWithDifferentId) {
 * Stylus pointer coordinates are resampled.
 */
TEST_F(InputConsumerResamplingTest, StylusEventIsResampled) {
    // Initial ACTION_DOWN should be separate, because the first consume event will only return
    // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an
    // InputEvent with a single action.
    mClientTestChannel->enqueueMessage(nextPointerMessage(
            {0ms,
@@ -332,9 +331,8 @@ TEST_F(InputConsumerResamplingTest, StylusEventIsResampled) {
 * Mouse pointer coordinates are resampled.
 */
TEST_F(InputConsumerResamplingTest, MouseEventIsResampled) {
    // Initial ACTION_DOWN should be separate, because the first consume event will only return
    // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an
    // InputEvent with a single action.

    mClientTestChannel->enqueueMessage(nextPointerMessage(
            {0ms,
             {Pointer{.id = 0, .x = 10.0f, .y = 20.0f, .toolType = ToolType::MOUSE}},
@@ -391,7 +389,7 @@ TEST_F(InputConsumerResamplingTest, MouseEventIsResampled) {
 * Motion events with palm tool type are not resampled.
 */
TEST_F(InputConsumerResamplingTest, PalmEventIsNotResampled) {
    // Initial ACTION_DOWN should be separate, because the first consume event will only return
    // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an
    // InputEvent with a single action.
    mClientTestChannel->enqueueMessage(nextPointerMessage(
            {0ms,
@@ -431,4 +429,43 @@ TEST_F(InputConsumerResamplingTest, PalmEventIsNotResampled) {
    mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
}

/**
 * Event should not be resampled when sample time is equal to event time.
 */
TEST_F(InputConsumerResamplingTest, SampleTimeEqualsEventTime) {
    // Send the initial ACTION_DOWN separately, so that the first consumed event will only return an
    // InputEvent with a single action.
    mClientTestChannel->enqueueMessage(nextPointerMessage(
            {0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN}));

    mClientTestChannel->assertNoSentMessages();

    invokeLooperCallback();
    assertReceivedMotionEvent({InputEventEntry{0ms,
                                               {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}},
                                               AMOTION_EVENT_ACTION_DOWN}});

    // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
    mClientTestChannel->enqueueMessage(nextPointerMessage(
            {10ms, {Pointer{.id = 0, .x = 20.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}));
    mClientTestChannel->enqueueMessage(nextPointerMessage(
            {20ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}));

    invokeLooperCallback();
    mConsumer->consumeBatchedInputEvents(nanoseconds{20ms + 5ms /*RESAMPLE_LATENCY*/}.count());

    // MotionEvent should not resampled because the resample time falls exactly on the existing
    // event time.
    assertReceivedMotionEvent({InputEventEntry{10ms,
                                               {Pointer{.id = 0, .x = 20.0f, .y = 30.0f}},
                                               AMOTION_EVENT_ACTION_MOVE},
                               InputEventEntry{20ms,
                                               {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}},
                                               AMOTION_EVENT_ACTION_MOVE}});

    mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
    mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
    mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
}

} // namespace android