Skip to content

Commit 4679e55

Browse files
author
Paul Ramirez
committed
Add logic to overwrite pointer coordinates if event time is too old
Included OldEventReceivedAfterResampleOccurs from TouchResampling_test.cpp, and added the missing logic in LegacyResampler to pass the test. The CL wrongly assumes pointer information guarantees between motion events, that is, pointer IDs can appear in different order between samples. This issue is fixed in the second to last CL in the relation chain by using an associative array as a data structure to store and access pointer properties and coordinates. Bug: 297226446 Flag: EXEMPT refactor Test: TEST=libinput_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST --gtest_filter="InputConsumerResamplingTest*" Change-Id: I41cb79eaba965cfdfe7db68c388cb5d0ffa406f3
1 parent 4d3b03a commit 4679e55

3 files changed

Lines changed: 80 additions & 0 deletions

File tree

include/input/Resampler.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ class LegacyResampler final : public Resampler {
166166
*/
167167
void overwriteStillPointers(MotionEvent& motionEvent, size_t sampleIndex) const;
168168

169+
/**
170+
* Overwrites the pointer coordinates of a sample with event time older than
171+
* that of mPreviousPrediction.
172+
*/
173+
void overwriteOldPointers(MotionEvent& motionEvent, size_t sampleIndex) const;
174+
169175
inline static void addSampleToMotionEvent(const Sample& sample, MotionEvent& motionEvent);
170176
};
171177
} // namespace android

libs/input/Resampler.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ void LegacyResampler::overwriteMotionEventSamples(MotionEvent& motionEvent) cons
271271
const size_t numSamples = motionEvent.getHistorySize() + 1;
272272
for (size_t sampleIndex = 0; sampleIndex < numSamples; ++sampleIndex) {
273273
overwriteStillPointers(motionEvent, sampleIndex);
274+
overwriteOldPointers(motionEvent, sampleIndex);
274275
}
275276
}
276277

@@ -289,6 +290,24 @@ void LegacyResampler::overwriteStillPointers(MotionEvent& motionEvent, size_t sa
289290
}
290291
}
291292

293+
void LegacyResampler::overwriteOldPointers(MotionEvent& motionEvent, size_t sampleIndex) const {
294+
if (!mPreviousPrediction.has_value()) {
295+
return;
296+
}
297+
if (nanoseconds{motionEvent.getHistoricalEventTime(sampleIndex)} <
298+
mPreviousPrediction->eventTime) {
299+
LOG_IF(INFO, debugResampling())
300+
<< "Motion event sample older than predicted sample. Overwriting event time from "
301+
<< motionEvent.getHistoricalEventTime(sampleIndex) << "ns to "
302+
<< mPreviousPrediction->eventTime.count() << "ns.";
303+
for (size_t pointerIndex = 0; pointerIndex < motionEvent.getPointerCount();
304+
++pointerIndex) {
305+
setMotionEventPointerCoords(motionEvent, sampleIndex, pointerIndex,
306+
mPreviousPrediction->pointers[pointerIndex].coords);
307+
}
308+
}
309+
}
310+
292311
void LegacyResampler::resampleMotionEvent(nanoseconds frameTime, MotionEvent& motionEvent,
293312
const InputMessage* futureSample) {
294313
const nanoseconds resampleTime = frameTime - RESAMPLE_LATENCY;

libs/input/tests/InputConsumerResampling_test.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,4 +511,59 @@ TEST_F(InputConsumerResamplingTest, ResampledValueIsUsedForIdenticalCoordinates)
511511
mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
512512
}
513513

514+
TEST_F(InputConsumerResamplingTest, OldEventReceivedAfterResampleOccurs) {
515+
// Send the initial ACTION_DOWN separately, so that the first consumed event will only return an
516+
// InputEvent with a single action.
517+
mClientTestChannel->enqueueMessage(nextPointerMessage(
518+
{0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN}));
519+
520+
invokeLooperCallback();
521+
assertReceivedMotionEvent({InputEventEntry{0ms,
522+
{Pointer{.id = 0, .x = 10.0f, .y = 20.0f}},
523+
AMOTION_EVENT_ACTION_DOWN}});
524+
525+
// Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
526+
mClientTestChannel->enqueueMessage(nextPointerMessage(
527+
{10ms, {Pointer{.id = 0, .x = 20.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}));
528+
mClientTestChannel->enqueueMessage(nextPointerMessage(
529+
{20ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}));
530+
531+
invokeLooperCallback();
532+
mConsumer->consumeBatchedInputEvents(nanoseconds{35ms}.count());
533+
assertReceivedMotionEvent(
534+
{InputEventEntry{10ms,
535+
{Pointer{.id = 0, .x = 20.0f, .y = 30.0f}},
536+
AMOTION_EVENT_ACTION_MOVE},
537+
InputEventEntry{20ms,
538+
{Pointer{.id = 0, .x = 30.0f, .y = 30.0f}},
539+
AMOTION_EVENT_ACTION_MOVE},
540+
InputEventEntry{25ms,
541+
{Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}},
542+
AMOTION_EVENT_ACTION_MOVE}});
543+
544+
// Above, the resampled event is at 25ms rather than at 30 ms = 35ms - RESAMPLE_LATENCY
545+
// because we are further bound by how far we can extrapolate by the "last time delta".
546+
// That's 50% of (20 ms - 10ms) => 5ms. So we can't predict more than 5 ms into the future
547+
// from the event at 20ms, which is why the resampled event is at t = 25 ms.
548+
549+
// We resampled the event to 25 ms. Now, an older 'real' event comes in.
550+
mClientTestChannel->enqueueMessage(nextPointerMessage(
551+
{24ms, {Pointer{.id = 0, .x = 40.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}));
552+
553+
invokeLooperCallback();
554+
mConsumer->consumeBatchedInputEvents(nanoseconds{50ms}.count());
555+
assertReceivedMotionEvent(
556+
{InputEventEntry{24ms,
557+
{Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}},
558+
AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten
559+
InputEventEntry{26ms,
560+
{Pointer{.id = 0, .x = 45.0f, .y = 30.0f, .isResampled = true}},
561+
AMOTION_EVENT_ACTION_MOVE}}); // resampled event, rewritten
562+
563+
mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
564+
mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
565+
mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
566+
mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
567+
}
568+
514569
} // namespace android

0 commit comments

Comments
 (0)