Ignore resampled values when computing velocity

VelocityTracker should only operate on the actual data produced by the
touchscreen. It should not use the fake, synthesized data during the
computation.
Using such data can cause unwanted artifacts such as backwards fling,
etc.

Bug: 167946721
Test: m libinput_tests && $ANDROID_HOST_OUT/nativetest64/libinput_tests/libinput_tests
Change-Id: I1ffdc1d38b0b335419f20c7bdd0d4473942bbf57
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 1cd782d..3632914 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -332,11 +332,13 @@
             return;
     }
 
-    size_t historySize = event->getHistorySize();
+    const size_t historySize = event->getHistorySize();
     for (size_t h = 0; h <= historySize; h++) {
-        nsecs_t eventTime = event->getHistoricalEventTime(h);
+        const nsecs_t eventTime = event->getHistoricalEventTime(h);
         for (size_t i = 0; i < event->getPointerCount(); i++) {
-            // TODO(b/167946721): skip resampled samples
+            if (event->isResampled(i, h)) {
+                continue; // skip resampled samples
+            }
             const int32_t pointerId = event->getPointerId(i);
             for (int32_t axis : axesToProcess) {
                 const float position = event->getHistoricalAxisValue(axis, i, h);
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 2678f2f..c6ad3a2 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -84,6 +84,8 @@
     float x;
     float y;
 
+    bool isResampled = false;
+
     /**
      * If both values are NAN, then this is considered to be an empty entry (no pointer data).
      * If only one of the values is NAN, this is still a valid entry,
@@ -203,10 +205,11 @@
 
             coords[pointerIndex].clear();
             // We are treating column positions as pointerId
-            EXPECT_TRUE(entry.positions[pointerId].isValid()) <<
-                    "The entry at pointerId must be valid";
-            coords[pointerIndex].setAxisValue(AMOTION_EVENT_AXIS_X, entry.positions[pointerId].x);
-            coords[pointerIndex].setAxisValue(AMOTION_EVENT_AXIS_Y, entry.positions[pointerId].y);
+            const Position& position = entry.positions[pointerId];
+            EXPECT_TRUE(position.isValid()) << "The entry at " << pointerId << " must be valid";
+            coords[pointerIndex].setAxisValue(AMOTION_EVENT_AXIS_X, position.x);
+            coords[pointerIndex].setAxisValue(AMOTION_EVENT_AXIS_Y, position.y);
+            coords[pointerIndex].isResampled = position.isResampled;
 
             properties[pointerIndex].id = pointerId;
             properties[pointerIndex].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
@@ -375,6 +378,44 @@
     EXPECT_FALSE(computedVelocity.getVelocity(AMOTION_EVENT_AXIS_X, MAX_POINTER_ID + 1));
 }
 
+/**
+ * For a single pointer, the resampled data is ignored.
+ */
+TEST_F(VelocityTrackerTest, SinglePointerResampledData) {
+    std::vector<PlanarMotionEventEntry> motions = {{10ms, {{1, 2}}},
+                                                   {20ms, {{2, 4}}},
+                                                   {30ms, {{3, 6}}},
+                                                   {35ms, {{30, 60, .isResampled = true}}},
+                                                   {40ms, {{4, 8}}}};
+
+    computeAndCheckVelocity(VelocityTracker::Strategy::DEFAULT, motions, AMOTION_EVENT_AXIS_X, 100);
+    computeAndCheckVelocity(VelocityTracker::Strategy::DEFAULT, motions, AMOTION_EVENT_AXIS_Y, 200);
+}
+
+/**
+ * For multiple pointers, the resampled data is ignored on a per-pointer basis. If a certain pointer
+ * does not have a resampled value, all of the points are used.
+ */
+TEST_F(VelocityTrackerTest, MultiPointerResampledData) {
+    std::vector<PlanarMotionEventEntry> motions = {
+            {0ms, {{0, 0}}},
+            {10ms, {{1, 0}, {1, 0}}},
+            {20ms, {{2, 0}, {2, 0}}},
+            {30ms, {{3, 0}, {3, 0}}},
+            {35ms, {{30, 0, .isResampled = true}, {30, 0}}},
+            {40ms, {{4, 0}, {4, 0}}},
+            {45ms, {{5, 0}}}, // ACTION_UP
+    };
+
+    // Sample at t=35ms breaks trend. It's marked as resampled for the first pointer, so it should
+    // be ignored, and the resulting velocity should be linear. For the second pointer, it's not
+    // resampled, so it should cause the velocity to be non-linear.
+    computeAndCheckVelocity(VelocityTracker::Strategy::DEFAULT, motions, AMOTION_EVENT_AXIS_X, 100,
+                            /*pointerId=*/0);
+    computeAndCheckVelocity(VelocityTracker::Strategy::DEFAULT, motions, AMOTION_EVENT_AXIS_X, 3455,
+                            /*pointerId=*/1);
+}
+
 TEST_F(VelocityTrackerTest, TestGetComputedVelocity) {
     std::vector<PlanarMotionEventEntry> motions = {
             {235089067457000ns, {{528.00, 0}}}, {235089084684000ns, {{527.00, 0}}},