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

Commit 09b2388b authored by Hiroki Sato's avatar Hiroki Sato
Browse files

Apply input resampling for motion events of ToolType::MOUSE and STYLUS

As the resampling is performed for better scrolling, even when a user
is dragging with a mouse or a stylus, we'd like to do the same as
touch inputs.

Also, when an event being resampled has any pointer with a tool type
that we don’t resample, the resampled event has an old coordinate but
a new timestamp. This event is confusing. With this change, when the
event has such a pointer, events won’t be resampled.

Bug: 337849873
Test: Enable debug and resampling happens for mouse events.
Test: TouchResamplingTest
Change-Id: I9344759e28685a08e233939761f93f0b3911413c
parent df55f52e
Loading
Loading
Loading
Loading
+26 −18
Original line number Diff line number Diff line
@@ -181,7 +181,8 @@ inline bool isPointerEvent(int32_t source) {
}

bool shouldResampleTool(ToolType toolType) {
    return toolType == ToolType::FINGER || toolType == ToolType::UNKNOWN;
    return toolType == ToolType::FINGER || toolType == ToolType::MOUSE ||
            toolType == ToolType::STYLUS || toolType == ToolType::UNKNOWN;
}

} // namespace
@@ -592,6 +593,11 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
            ALOGD_IF(debugResampling(), "Not resampled, missing id %d", id);
            return;
        }
        if (!shouldResampleTool(event->getToolType(i))) {
            ALOGD_IF(debugResampling(),
                     "Not resampled, containing unsupported tool type at pointer %d", id);
            return;
        }
    }

    // Find the data to use for resampling.
@@ -639,10 +645,18 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
    }

    if (current->eventTime == sampleTime) {
        // Prevents having 2 events with identical times and coordinates.
        ALOGD_IF(debugResampling(), "Not resampled, 2 events with identical times.");
        return;
    }

    for (size_t i = 0; i < pointerCount; i++) {
        uint32_t id = event->getPointerId(i);
        if (!other->idBits.hasBit(id)) {
            ALOGD_IF(debugResampling(), "Not resampled, the other doesn't have pointer id %d.", id);
            return;
        }
    }

    // Resample touch coordinates.
    History oldLastResample;
    oldLastResample.initializeFrom(touchState.lastResample);
@@ -670,7 +684,6 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
        const PointerCoords& currentCoords = current->getPointerById(id);
        resampledCoords = currentCoords;
        resampledCoords.isResampled = true;
        if (other->idBits.hasBit(id) && shouldResampleTool(event->getToolType(i))) {
        const PointerCoords& otherCoords = other->getPointerById(id);
        resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
                                     lerp(currentCoords.getX(), otherCoords.getX(), alpha));
@@ -681,11 +694,6 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
                 "other (%0.3f, %0.3f), alpha %0.3f",
                 id, resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
                 currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha);
        } else {
            ALOGD_IF(debugResampling(), "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f)", id,
                     resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(),
                     currentCoords.getY());
        }
    }

    event->addSample(sampleTime, touchState.lastResample.pointers);
+80 −5
Original line number Diff line number Diff line
@@ -297,10 +297,9 @@ TEST_F(TouchResamplingTest, EventIsResampledWithDifferentId) {
}

/**
 * Stylus pointer coordinates are not resampled, but an event is still generated for the batch with
 * a resampled timestamp and should be marked as such.
 * Stylus pointer coordinates are resampled.
 */
TEST_F(TouchResamplingTest, StylusCoordinatesNotResampledFor) {
TEST_F(TouchResamplingTest, StylusEventIsResampled) {
    std::chrono::nanoseconds frameTime;
    std::vector<InputEventEntry> entries, expectedEntries;

@@ -330,14 +329,90 @@ TEST_F(TouchResamplingTest, StylusCoordinatesNotResampledFor) {
            //      id  x   y
            {10ms, {{0, 20, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE},
            {20ms, {{0, 30, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE},
            // A resampled event is generated, but the stylus coordinates are not resampled.
            {25ms,
             {{0, 30, 30, .toolType = ToolType::STYLUS, .isResampled = true}},
             {{0, 35, 30, .toolType = ToolType::STYLUS, .isResampled = true}},
             AMOTION_EVENT_ACTION_MOVE},
    };
    consumeInputEventEntries(expectedEntries, frameTime);
}

/**
 * Mouse pointer coordinates are resampled.
 */
TEST_F(TouchResamplingTest, MouseEventIsResampled) {
    std::chrono::nanoseconds frameTime;
    std::vector<InputEventEntry> entries, expectedEntries;

    // Initial ACTION_DOWN should be separate, because the first consume event will only return
    // InputEvent with a single action.
    entries = {
            //      id  x   y
            {0ms, {{0, 10, 20, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_DOWN},
    };
    publishInputEventEntries(entries);
    frameTime = 5ms;
    expectedEntries = {
            //      id  x   y
            {0ms, {{0, 10, 20, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_DOWN},
    };
    consumeInputEventEntries(expectedEntries, frameTime);

    // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
    entries = {
            //      id  x   y
            {10ms, {{0, 20, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
            {20ms, {{0, 30, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
    };
    publishInputEventEntries(entries);
    frameTime = 35ms;
    expectedEntries = {
            //      id  x   y
            {10ms, {{0, 20, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
            {20ms, {{0, 30, 30, .toolType = ToolType::MOUSE}}, AMOTION_EVENT_ACTION_MOVE},
            {25ms,
             {{0, 35, 30, .toolType = ToolType::MOUSE, .isResampled = true}},
             AMOTION_EVENT_ACTION_MOVE},
    };
    consumeInputEventEntries(expectedEntries, frameTime);
}

/**
 * Motion events with palm tool type are not resampled.
 */
TEST_F(TouchResamplingTest, PalmEventIsNotResampled) {
    std::chrono::nanoseconds frameTime;
    std::vector<InputEventEntry> entries, expectedEntries;

    // Initial ACTION_DOWN should be separate, because the first consume event will only return
    // InputEvent with a single action.
    entries = {
            //      id  x   y
            {0ms, {{0, 10, 20, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_DOWN},
    };
    publishInputEventEntries(entries);
    frameTime = 5ms;
    expectedEntries = {
            //      id  x   y
            {0ms, {{0, 10, 20, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_DOWN},
    };
    consumeInputEventEntries(expectedEntries, frameTime);

    // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
    entries = {
            //      id  x   y
            {10ms, {{0, 20, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
            {20ms, {{0, 30, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
    };
    publishInputEventEntries(entries);
    frameTime = 35ms;
    expectedEntries = {
            //      id  x   y
            {10ms, {{0, 20, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
            {20ms, {{0, 30, 30, .toolType = ToolType::PALM}}, AMOTION_EVENT_ACTION_MOVE},
    };
    consumeInputEventEntries(expectedEntries, frameTime);
}

/**
 * Event should not be resampled when sample time is equal to event time.
 */