Loading libs/input/tests/InputConsumerResampling_test.cpp +153 −6 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ namespace { using std::chrono::nanoseconds; using namespace std::chrono_literals; const std::chrono::milliseconds RESAMPLE_LATENCY{5}; struct Pointer { int32_t id{0}; float x{0.0f}; Loading Loading @@ -440,7 +442,7 @@ TEST_F(InputConsumerResamplingTest, SampleTimeEqualsEventTime) { {20ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{20ms + 5ms /*RESAMPLE_LATENCY*/}.count()); mConsumer->consumeBatchedInputEvents(nanoseconds{20ms + RESAMPLE_LATENCY}.count()); // MotionEvent should not resampled because the resample time falls exactly on the existing // event time. Loading Loading @@ -496,14 +498,15 @@ TEST_F(InputConsumerResamplingTest, ResampledValueIsUsedForIdenticalCoordinates) {40ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{45ms + 5ms /*RESAMPLE_LATENCY*/}.count()); mConsumer->consumeBatchedInputEvents(nanoseconds{45ms + RESAMPLE_LATENCY}.count()); // Original and resampled event should be both overwritten. assertReceivedMotionEvent( {InputEventEntry{40ms, {Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{45ms, {Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}}); // resampled event, rewritten AMOTION_EVENT_ACTION_MOVE}}); mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true); Loading Loading @@ -552,13 +555,14 @@ TEST_F(InputConsumerResamplingTest, OldEventReceivedAfterResampleOccurs) { invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{50ms}.count()); // Original and resampled event should be both overwritten. assertReceivedMotionEvent( {InputEventEntry{24ms, {Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{26ms, {Pointer{.id = 0, .x = 45.0f, .y = 30.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}}); // resampled event, rewritten AMOTION_EVENT_ACTION_MOVE}}); mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true); Loading Loading @@ -594,4 +598,147 @@ TEST_F(InputConsumerResamplingTest, DoNotResampleWhenFrameTimeIsNotAvailable) { mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true); } TEST_F(InputConsumerResamplingTest, TwoPointersAreResampledIndependently) { // Full action for when a pointer with index=1 appears (some other pointer must already be // present) const int32_t actionPointer1Down = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); // Full action for when a pointer with index=0 disappears (some other pointer must still remain) const int32_t actionPointer0Up = AMOTION_EVENT_ACTION_POINTER_UP + (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); mClientTestChannel->enqueueMessage(nextPointerMessage( {0ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}}, AMOTION_EVENT_ACTION_DOWN})); mClientTestChannel->assertNoSentMessages(); invokeLooperCallback(); assertReceivedMotionEvent({InputEventEntry{0ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}}, AMOTION_EVENT_ACTION_DOWN}}); mClientTestChannel->enqueueMessage(nextPointerMessage( {10ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{10ms + RESAMPLE_LATENCY}.count()); // Not resampled value because requestedFrameTime - RESAMPLE_LATENCY == eventTime assertReceivedMotionEvent({InputEventEntry{10ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}}, AMOTION_EVENT_ACTION_MOVE}}); // Second pointer id=1 appears mClientTestChannel->enqueueMessage( nextPointerMessage({15ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}, Pointer{.id = 1, .x = 500.0f, .y = 500.0f}}, actionPointer1Down})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{20ms + RESAMPLE_LATENCY}.count()); // Not resampled value because requestedFrameTime - RESAMPLE_LATENCY == eventTime. assertReceivedMotionEvent({InputEventEntry{15ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}, Pointer{.id = 1, .x = 500.0f, .y = 500.0f}}, actionPointer1Down}}); // Both pointers move mClientTestChannel->enqueueMessage( nextPointerMessage({30ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}, Pointer{.id = 1, .x = 500.0f, .y = 500.0f}}, AMOTION_EVENT_ACTION_MOVE})); mClientTestChannel->enqueueMessage( nextPointerMessage({40ms, {Pointer{.id = 0, .x = 120.0f, .y = 120.0f}, Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{45ms + RESAMPLE_LATENCY}.count()); assertReceivedMotionEvent( {InputEventEntry{30ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}, Pointer{.id = 1, .x = 500.0f, .y = 500.0f}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{40ms, {Pointer{.id = 0, .x = 120.0f, .y = 120.0f}, Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{45ms, {Pointer{.id = 0, .x = 130.0f, .y = 130.0f, .isResampled = true}, Pointer{.id = 1, .x = 650.0f, .y = 650.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}}); // Both pointers move again mClientTestChannel->enqueueMessage( nextPointerMessage({60ms, {Pointer{.id = 0, .x = 120.0f, .y = 120.0f}, Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE})); mClientTestChannel->enqueueMessage( nextPointerMessage({70ms, {Pointer{.id = 0, .x = 130.0f, .y = 130.0f}, Pointer{.id = 1, .x = 700.0f, .y = 700.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{75ms + RESAMPLE_LATENCY}.count()); /* * The pointer id 0 at t = 60 should not be equal to 120 because the value was received twice, * and resampled to 130. Therefore, if we reported 130, then we should continue to report it as * such. Likewise, with pointer id 1. */ // Not 120 because it matches a previous real event. assertReceivedMotionEvent( {InputEventEntry{60ms, {Pointer{.id = 0, .x = 130.0f, .y = 130.0f, .isResampled = true}, Pointer{.id = 1, .x = 650.0f, .y = 650.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{70ms, {Pointer{.id = 0, .x = 130.0f, .y = 130.0f}, Pointer{.id = 1, .x = 700.0f, .y = 700.0f}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{75ms, {Pointer{.id = 0, .x = 135.0f, .y = 135.0f, .isResampled = true}, Pointer{.id = 1, .x = 750.0f, .y = 750.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}}); // First pointer id=0 leaves the screen mClientTestChannel->enqueueMessage( nextPointerMessage({80ms, {Pointer{.id = 0, .x = 120.0f, .y = 120.0f}, Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, actionPointer0Up})); invokeLooperCallback(); // Not resampled event for ACTION_POINTER_UP assertReceivedMotionEvent({InputEventEntry{80ms, {Pointer{.id = 0, .x = 120.0f, .y = 120.0f}, Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, actionPointer0Up}}); // Remaining pointer id=1 is still present, but doesn't move mClientTestChannel->enqueueMessage(nextPointerMessage( {90ms, {Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{100ms}.count()); /* * The latest event with ACTION_MOVE was at t = 70 with value = 700. Thus, the resampled value * is 700 + ((95 - 70)/(90 - 70))*(600 - 700) = 575. */ assertReceivedMotionEvent( {InputEventEntry{90ms, {Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{95ms, {Pointer{.id = 1, .x = 575.0f, .y = 575.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}}); } } // namespace android libs/input/tests/TouchResampling_test.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -571,11 +571,12 @@ TEST_F(TouchResamplingTest, TwoPointersAreResampledIndependently) { std::chrono::nanoseconds frameTime; std::vector<InputEventEntry> entries, expectedEntries; // full action for when a pointer with id=1 appears (some other pointer must already be present) // full action for when a pointer with index=1 appears (some other pointer must already be // present) constexpr int32_t actionPointer1Down = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); // full action for when a pointer with id=0 disappears (some other pointer must still remain) // full action for when a pointer with index=0 disappears (some other pointer must still remain) constexpr int32_t actionPointer0Up = AMOTION_EVENT_ACTION_POINTER_UP + (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); Loading Loading
libs/input/tests/InputConsumerResampling_test.cpp +153 −6 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ namespace { using std::chrono::nanoseconds; using namespace std::chrono_literals; const std::chrono::milliseconds RESAMPLE_LATENCY{5}; struct Pointer { int32_t id{0}; float x{0.0f}; Loading Loading @@ -440,7 +442,7 @@ TEST_F(InputConsumerResamplingTest, SampleTimeEqualsEventTime) { {20ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{20ms + 5ms /*RESAMPLE_LATENCY*/}.count()); mConsumer->consumeBatchedInputEvents(nanoseconds{20ms + RESAMPLE_LATENCY}.count()); // MotionEvent should not resampled because the resample time falls exactly on the existing // event time. Loading Loading @@ -496,14 +498,15 @@ TEST_F(InputConsumerResamplingTest, ResampledValueIsUsedForIdenticalCoordinates) {40ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{45ms + 5ms /*RESAMPLE_LATENCY*/}.count()); mConsumer->consumeBatchedInputEvents(nanoseconds{45ms + RESAMPLE_LATENCY}.count()); // Original and resampled event should be both overwritten. assertReceivedMotionEvent( {InputEventEntry{40ms, {Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{45ms, {Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}}); // resampled event, rewritten AMOTION_EVENT_ACTION_MOVE}}); mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true); Loading Loading @@ -552,13 +555,14 @@ TEST_F(InputConsumerResamplingTest, OldEventReceivedAfterResampleOccurs) { invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{50ms}.count()); // Original and resampled event should be both overwritten. assertReceivedMotionEvent( {InputEventEntry{24ms, {Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{26ms, {Pointer{.id = 0, .x = 45.0f, .y = 30.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}}); // resampled event, rewritten AMOTION_EVENT_ACTION_MOVE}}); mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true); mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true); Loading Loading @@ -594,4 +598,147 @@ TEST_F(InputConsumerResamplingTest, DoNotResampleWhenFrameTimeIsNotAvailable) { mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true); } TEST_F(InputConsumerResamplingTest, TwoPointersAreResampledIndependently) { // Full action for when a pointer with index=1 appears (some other pointer must already be // present) const int32_t actionPointer1Down = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); // Full action for when a pointer with index=0 disappears (some other pointer must still remain) const int32_t actionPointer0Up = AMOTION_EVENT_ACTION_POINTER_UP + (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); mClientTestChannel->enqueueMessage(nextPointerMessage( {0ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}}, AMOTION_EVENT_ACTION_DOWN})); mClientTestChannel->assertNoSentMessages(); invokeLooperCallback(); assertReceivedMotionEvent({InputEventEntry{0ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}}, AMOTION_EVENT_ACTION_DOWN}}); mClientTestChannel->enqueueMessage(nextPointerMessage( {10ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{10ms + RESAMPLE_LATENCY}.count()); // Not resampled value because requestedFrameTime - RESAMPLE_LATENCY == eventTime assertReceivedMotionEvent({InputEventEntry{10ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}}, AMOTION_EVENT_ACTION_MOVE}}); // Second pointer id=1 appears mClientTestChannel->enqueueMessage( nextPointerMessage({15ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}, Pointer{.id = 1, .x = 500.0f, .y = 500.0f}}, actionPointer1Down})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{20ms + RESAMPLE_LATENCY}.count()); // Not resampled value because requestedFrameTime - RESAMPLE_LATENCY == eventTime. assertReceivedMotionEvent({InputEventEntry{15ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}, Pointer{.id = 1, .x = 500.0f, .y = 500.0f}}, actionPointer1Down}}); // Both pointers move mClientTestChannel->enqueueMessage( nextPointerMessage({30ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}, Pointer{.id = 1, .x = 500.0f, .y = 500.0f}}, AMOTION_EVENT_ACTION_MOVE})); mClientTestChannel->enqueueMessage( nextPointerMessage({40ms, {Pointer{.id = 0, .x = 120.0f, .y = 120.0f}, Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{45ms + RESAMPLE_LATENCY}.count()); assertReceivedMotionEvent( {InputEventEntry{30ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}, Pointer{.id = 1, .x = 500.0f, .y = 500.0f}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{40ms, {Pointer{.id = 0, .x = 120.0f, .y = 120.0f}, Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{45ms, {Pointer{.id = 0, .x = 130.0f, .y = 130.0f, .isResampled = true}, Pointer{.id = 1, .x = 650.0f, .y = 650.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}}); // Both pointers move again mClientTestChannel->enqueueMessage( nextPointerMessage({60ms, {Pointer{.id = 0, .x = 120.0f, .y = 120.0f}, Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE})); mClientTestChannel->enqueueMessage( nextPointerMessage({70ms, {Pointer{.id = 0, .x = 130.0f, .y = 130.0f}, Pointer{.id = 1, .x = 700.0f, .y = 700.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{75ms + RESAMPLE_LATENCY}.count()); /* * The pointer id 0 at t = 60 should not be equal to 120 because the value was received twice, * and resampled to 130. Therefore, if we reported 130, then we should continue to report it as * such. Likewise, with pointer id 1. */ // Not 120 because it matches a previous real event. assertReceivedMotionEvent( {InputEventEntry{60ms, {Pointer{.id = 0, .x = 130.0f, .y = 130.0f, .isResampled = true}, Pointer{.id = 1, .x = 650.0f, .y = 650.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{70ms, {Pointer{.id = 0, .x = 130.0f, .y = 130.0f}, Pointer{.id = 1, .x = 700.0f, .y = 700.0f}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{75ms, {Pointer{.id = 0, .x = 135.0f, .y = 135.0f, .isResampled = true}, Pointer{.id = 1, .x = 750.0f, .y = 750.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}}); // First pointer id=0 leaves the screen mClientTestChannel->enqueueMessage( nextPointerMessage({80ms, {Pointer{.id = 0, .x = 120.0f, .y = 120.0f}, Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, actionPointer0Up})); invokeLooperCallback(); // Not resampled event for ACTION_POINTER_UP assertReceivedMotionEvent({InputEventEntry{80ms, {Pointer{.id = 0, .x = 120.0f, .y = 120.0f}, Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, actionPointer0Up}}); // Remaining pointer id=1 is still present, but doesn't move mClientTestChannel->enqueueMessage(nextPointerMessage( {90ms, {Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE})); invokeLooperCallback(); mConsumer->consumeBatchedInputEvents(nanoseconds{100ms}.count()); /* * The latest event with ACTION_MOVE was at t = 70 with value = 700. Thus, the resampled value * is 700 + ((95 - 70)/(90 - 70))*(600 - 700) = 575. */ assertReceivedMotionEvent( {InputEventEntry{90ms, {Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE}, InputEventEntry{95ms, {Pointer{.id = 1, .x = 575.0f, .y = 575.0f, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE}}); } } // namespace android
libs/input/tests/TouchResampling_test.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -571,11 +571,12 @@ TEST_F(TouchResamplingTest, TwoPointersAreResampledIndependently) { std::chrono::nanoseconds frameTime; std::vector<InputEventEntry> entries, expectedEntries; // full action for when a pointer with id=1 appears (some other pointer must already be present) // full action for when a pointer with index=1 appears (some other pointer must already be // present) constexpr int32_t actionPointer1Down = AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); // full action for when a pointer with id=0 disappears (some other pointer must still remain) // full action for when a pointer with index=0 disappears (some other pointer must still remain) constexpr int32_t actionPointer0Up = AMOTION_EVENT_ACTION_POINTER_UP + (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); Loading