diff options
author | 2024-05-28 16:29:06 +0900 | |
---|---|---|
committer | 2024-06-03 01:09:28 +0000 | |
commit | 09b2388b8c1da1195675d91084a6215f2916d6be (patch) | |
tree | e51e312ace4496a675d351429b2018530ade269d | |
parent | df55f52e05eaac908ac93e09e7ae95148d9a0006 (diff) |
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
-rw-r--r-- | libs/input/InputConsumer.cpp | 44 | ||||
-rw-r--r-- | libs/input/tests/TouchResampling_test.cpp | 85 |
2 files changed, 106 insertions, 23 deletions
diff --git a/libs/input/InputConsumer.cpp b/libs/input/InputConsumer.cpp index abc039281a..fcf490d5f9 100644 --- a/libs/input/InputConsumer.cpp +++ b/libs/input/InputConsumer.cpp @@ -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,22 +684,16 @@ 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)); - resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, - lerp(currentCoords.getY(), otherCoords.getY(), alpha)); - ALOGD_IF(debugResampling(), - "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), " - "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()); - } + const PointerCoords& otherCoords = other->getPointerById(id); + resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X, + lerp(currentCoords.getX(), otherCoords.getX(), alpha)); + resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, + lerp(currentCoords.getY(), otherCoords.getY(), alpha)); + ALOGD_IF(debugResampling(), + "[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), " + "other (%0.3f, %0.3f), alpha %0.3f", + id, resampledCoords.getX(), resampledCoords.getY(), currentCoords.getX(), + currentCoords.getY(), otherCoords.getX(), otherCoords.getY(), alpha); } event->addSample(sampleTime, touchState.lastResample.pointers); diff --git a/libs/input/tests/TouchResampling_test.cpp b/libs/input/tests/TouchResampling_test.cpp index 2dc9fdb7f1..8d8b5300c1 100644 --- a/libs/input/tests/TouchResampling_test.cpp +++ b/libs/input/tests/TouchResampling_test.cpp @@ -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,15 +329,91 @@ 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. */ TEST_F(TouchResamplingTest, SampleTimeEqualsEventTime) { |