summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Philip Quinn <pquinn@google.com> 2022-12-20 18:17:55 -0800
committer Philip Quinn <pquinn@google.com> 2023-01-05 18:08:33 -0800
commitafb312889849d435e59f8e1014e1385ac419c4ea (patch)
tree920730b1ad0334324ab1e1459bbe9cc45c0578f5
parent015ae27a731030bd87b8274fe64ac45eceb7d7f7 (diff)
Add isResampled field to PointerCoords.
This field is set if a pointer's coordinate data were generated by input resampling and did not originate from the input device. Bug: 167946721 Test: atest libinput_tests Change-Id: I30d9aee85d462e6536fa33be5242365b52a11a6c
-rw-r--r--include/input/Input.h13
-rw-r--r--libs/input/Input.cpp7
-rw-r--r--libs/input/InputTransport.cpp6
-rw-r--r--libs/input/tests/InputEvent_test.cpp18
-rw-r--r--libs/input/tests/StructLayout_test.cpp14
-rw-r--r--libs/input/tests/TouchResampling_test.cpp41
6 files changed, 78 insertions, 21 deletions
diff --git a/include/input/Input.h b/include/input/Input.h
index 1a35196036..08d9019911 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -368,7 +368,7 @@ constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits<floa
* Pointer coordinate data.
*/
struct PointerCoords {
- enum { MAX_AXES = 30 }; // 30 so that sizeof(PointerCoords) == 128
+ enum { MAX_AXES = 30 }; // 30 so that sizeof(PointerCoords) == 136
// Bitfield of axes that are present in this structure.
uint64_t bits __attribute__((aligned(8)));
@@ -377,8 +377,15 @@ struct PointerCoords {
// for each axis that is present in the structure according to 'bits'.
std::array<float, MAX_AXES> values;
+ // Whether these coordinate data were generated by resampling.
+ bool isResampled;
+
+ static_assert(sizeof(bool) == 1); // Ensure padding is correctly sized.
+ uint8_t empty[7];
+
inline void clear() {
BitSet64::clear(bits);
+ isResampled = false;
}
bool isEmpty() const {
@@ -769,6 +776,10 @@ public:
AMOTION_EVENT_AXIS_ORIENTATION, pointerIndex, historicalIndex);
}
+ inline bool isResampled(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->isResampled;
+ }
+
ssize_t findPointerIndex(int32_t pointerId) const;
void initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index d893cb99ba..cdc779dfd9 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -411,6 +411,8 @@ status_t PointerCoords::readFromParcel(Parcel* parcel) {
for (uint32_t i = 0; i < count; i++) {
values[i] = parcel->readFloat();
}
+
+ isResampled = parcel->readBool();
return OK;
}
@@ -421,6 +423,8 @@ status_t PointerCoords::writeToParcel(Parcel* parcel) const {
for (uint32_t i = 0; i < count; i++) {
parcel->writeFloat(values[i]);
}
+
+ parcel->writeBool(isResampled);
return OK;
}
#endif
@@ -440,6 +444,9 @@ bool PointerCoords::operator==(const PointerCoords& other) const {
return false;
}
}
+ if (isResampled != other.isResampled) {
+ return false;
+ }
return true;
}
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 8d8433b973..9f0a314041 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -267,6 +267,8 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const {
memcpy(&msg->body.motion.pointers[i].coords.values[0],
&body.motion.pointers[i].coords.values[0],
count * (sizeof(body.motion.pointers[i].coords.values[0])));
+ msg->body.motion.pointers[i].coords.isResampled =
+ body.motion.pointers[i].coords.isResampled;
}
break;
}
@@ -1079,6 +1081,7 @@ void InputConsumer::rewriteMessage(TouchState& state, InputMessage& msg) {
#endif
msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
+ msgCoords.isResampled = true;
} else {
state.lastResample.idBits.clearBit(id);
}
@@ -1191,6 +1194,8 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
// We maintain the previously resampled value for this pointer (stored in
// oldLastResample) when the coordinates for this pointer haven't changed since then.
// This way we don't introduce artificial jitter when pointers haven't actually moved.
+ // The isResampled flag isn't cleared as the values don't reflect what the device is
+ // actually reporting.
// We know here that the coordinates for the pointer haven't changed because we
// would've cleared the resampled bit in rewriteMessage if they had. We can't modify
@@ -1209,6 +1214,7 @@ void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
lerp(currentCoords.getX(), otherCoords.getX(), alpha));
resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
lerp(currentCoords.getY(), otherCoords.getY(), alpha));
+ resampledCoords.isResampled = true;
#if DEBUG_RESAMPLING
ALOGD("[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
"other (%0.3f, %0.3f), alpha %0.3f",
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 4b3124636b..8a6e983bb5 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -46,6 +46,7 @@ TEST_F(PointerCoordsTest, ClearSetsBitsToZero) {
coords.clear();
ASSERT_EQ(0ULL, coords.bits);
+ ASSERT_FALSE(coords.isResampled);
}
TEST_F(PointerCoordsTest, AxisValues) {
@@ -158,11 +159,13 @@ TEST_F(PointerCoordsTest, Parcel) {
outCoords.readFromParcel(&parcel);
ASSERT_EQ(0ULL, outCoords.bits);
+ ASSERT_FALSE(outCoords.isResampled);
// Round trip with some values.
parcel.freeData();
inCoords.setAxisValue(2, 5);
inCoords.setAxisValue(5, 8);
+ inCoords.isResampled = true;
inCoords.writeToParcel(&parcel);
parcel.setDataPosition(0);
@@ -171,6 +174,7 @@ TEST_F(PointerCoordsTest, Parcel) {
ASSERT_EQ(outCoords.bits, inCoords.bits);
ASSERT_EQ(outCoords.values[0], inCoords.values[0]);
ASSERT_EQ(outCoords.values[1], inCoords.values[1]);
+ ASSERT_TRUE(outCoords.isResampled);
}
@@ -263,6 +267,7 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 16);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 17);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 18);
+ pointerCoords[0].isResampled = true;
pointerCoords[1].clear();
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 20);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 21);
@@ -281,6 +286,7 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
mRawTransform, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2,
pointerProperties, pointerCoords);
+ pointerCoords[0].clear();
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 112);
@@ -290,6 +296,8 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 116);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 117);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 118);
+ pointerCoords[0].isResampled = true;
+ pointerCoords[1].clear();
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 120);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 121);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 122);
@@ -299,8 +307,10 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 126);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 127);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 128);
+ pointerCoords[1].isResampled = true;
event->addSample(ARBITRARY_EVENT_TIME + 1, pointerCoords);
+ pointerCoords[0].clear();
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 210);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 211);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 212);
@@ -310,6 +320,7 @@ void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 216);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 217);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 218);
+ pointerCoords[1].clear();
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 220);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 221);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 222);
@@ -457,6 +468,13 @@ void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
ASSERT_EQ(toScaledOrientation(128), event->getHistoricalOrientation(1, 1));
ASSERT_EQ(toScaledOrientation(218), event->getOrientation(0));
ASSERT_EQ(toScaledOrientation(228), event->getOrientation(1));
+
+ ASSERT_TRUE(event->isResampled(0, 0));
+ ASSERT_FALSE(event->isResampled(1, 0));
+ ASSERT_TRUE(event->isResampled(0, 1));
+ ASSERT_TRUE(event->isResampled(1, 1));
+ ASSERT_FALSE(event->isResampled(0, 2));
+ ASSERT_FALSE(event->isResampled(1, 2));
}
TEST_F(MotionEventTest, Properties) {
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 1c8658b69a..024b6d3d43 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -117,7 +117,7 @@ void TestHeaderSize() {
void TestBodySize() {
static_assert(sizeof(InputMessage::Body::Key) == 96);
- static_assert(sizeof(InputMessage::Body::Motion::Pointer) == 136);
+ static_assert(sizeof(InputMessage::Body::Motion::Pointer) == 144);
static_assert(sizeof(InputMessage::Body::Motion) ==
offsetof(InputMessage::Body::Motion, pointers) +
sizeof(InputMessage::Body::Motion::Pointer) * MAX_POINTERS);
@@ -137,8 +137,8 @@ void TestBodySize() {
static_assert(sizeof(InputMessage::Body) ==
offsetof(InputMessage::Body::Motion, pointers) +
sizeof(InputMessage::Body::Motion::Pointer) * MAX_POINTERS);
- static_assert(sizeof(InputMessage::Body) == 160 + 136 * 16);
- static_assert(sizeof(InputMessage::Body) == 2336);
+ static_assert(sizeof(InputMessage::Body) == 160 + 144 * 16);
+ static_assert(sizeof(InputMessage::Body) == 2464);
}
/**
@@ -148,8 +148,8 @@ void TestBodySize() {
* still helpful to compute to get an idea of the sizes that are involved.
*/
void TestWorstCaseInputMessageSize() {
- static_assert(sizeof(InputMessage) == /*header*/ 8 + /*body*/ 2336);
- static_assert(sizeof(InputMessage) == 2344);
+ static_assert(sizeof(InputMessage) == /*header*/ 8 + /*body*/ 2464);
+ static_assert(sizeof(InputMessage) == 2472);
}
/**
@@ -159,8 +159,8 @@ void CalculateSinglePointerInputMessageSize() {
constexpr size_t pointerCount = 1;
constexpr size_t bodySize = offsetof(InputMessage::Body::Motion, pointers) +
sizeof(InputMessage::Body::Motion::Pointer) * pointerCount;
- static_assert(bodySize == 160 + 136);
- static_assert(bodySize == 296); // For the total message size, add the small header
+ static_assert(bodySize == 160 + 144);
+ static_assert(bodySize == 304); // For the total message size, add the small header
}
// --- VerifiedInputEvent ---
diff --git a/libs/input/tests/TouchResampling_test.cpp b/libs/input/tests/TouchResampling_test.cpp
index c09a8e9358..d01258c783 100644
--- a/libs/input/tests/TouchResampling_test.cpp
+++ b/libs/input/tests/TouchResampling_test.cpp
@@ -31,6 +31,7 @@ struct Pointer {
int32_t id;
float x;
float y;
+ bool isResampled = false;
};
struct InputEventEntry {
@@ -190,6 +191,8 @@ void TouchResamplingTest::consumeInputEventEntries(const std::vector<InputEventE
ASSERT_EQ(entry.pointers[p].y,
motionEvent->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y,
motionEventPointerIndex, i));
+ ASSERT_EQ(entry.pointers[p].isResampled,
+ motionEvent->isResampled(motionEventPointerIndex, i));
}
}
@@ -244,7 +247,7 @@ TEST_F(TouchResamplingTest, EventIsResampled) {
// id x y
{10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
{20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
- {25ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ {25ms, {{0, 35, 30, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE},
};
consumeInputEventEntries(expectedEntries, frameTime);
}
@@ -283,7 +286,7 @@ TEST_F(TouchResamplingTest, EventIsResampledWithDifferentId) {
// id x y
{10ms, {{1, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
{20ms, {{1, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
- {25ms, {{1, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ {25ms, {{1, 35, 30, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE},
};
consumeInputEventEntries(expectedEntries, frameTime);
}
@@ -361,7 +364,7 @@ TEST_F(TouchResamplingTest, ResampledValueIsUsedForIdenticalCoordinates) {
// id x y
{10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
{20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
- {25ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ {25ms, {{0, 35, 30, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE},
};
consumeInputEventEntries(expectedEntries, frameTime);
@@ -375,8 +378,12 @@ TEST_F(TouchResamplingTest, ResampledValueIsUsedForIdenticalCoordinates) {
frameTime = 45ms + 5ms /*RESAMPLE_LATENCY*/;
expectedEntries = {
// id x y
- {40ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten
- {45ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled event, rewritten
+ {40ms,
+ {{0, 35, 30, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten
+ {45ms,
+ {{0, 35, 30, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE}, // resampled event, rewritten
};
consumeInputEventEntries(expectedEntries, frameTime);
}
@@ -411,7 +418,7 @@ TEST_F(TouchResamplingTest, OldEventReceivedAfterResampleOccurs) {
// id x y
{10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
{20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
- {25ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ {25ms, {{0, 35, 30, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE},
};
consumeInputEventEntries(expectedEntries, frameTime);
// Above, the resampled event is at 25ms rather than at 30 ms = 35ms - RESAMPLE_LATENCY
@@ -428,8 +435,12 @@ TEST_F(TouchResamplingTest, OldEventReceivedAfterResampleOccurs) {
frameTime = 50ms;
expectedEntries = {
// id x y
- {24ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten
- {26ms, {{0, 45, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled event, rewritten
+ {24ms,
+ {{0, 35, 30, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten
+ {26ms,
+ {{0, 45, 30, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE}, // resampled event, rewritten
};
consumeInputEventEntries(expectedEntries, frameTime);
}
@@ -499,7 +510,9 @@ TEST_F(TouchResamplingTest, TwoPointersAreResampledIndependently) {
// id x y
{30ms, {{0, 100, 100}, {1, 500, 500}}, AMOTION_EVENT_ACTION_MOVE},
{40ms, {{0, 120, 120}, {1, 600, 600}}, AMOTION_EVENT_ACTION_MOVE},
- {45ms, {{0, 130, 130}, {1, 650, 650}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ {45ms,
+ {{0, 130, 130, .isResampled = true}, {1, 650, 650, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE},
};
consumeInputEventEntries(expectedEntries, frameTime);
@@ -518,11 +531,13 @@ TEST_F(TouchResamplingTest, TwoPointersAreResampledIndependently) {
*/
expectedEntries = {
{60ms,
- {{0, 130, 130}, // not 120! because it matches previous real event
- {1, 650, 650}},
+ {{0, 130, 130, .isResampled = true}, // not 120! because it matches previous real event
+ {1, 650, 650, .isResampled = true}},
AMOTION_EVENT_ACTION_MOVE},
{70ms, {{0, 130, 130}, {1, 700, 700}}, AMOTION_EVENT_ACTION_MOVE},
- {75ms, {{0, 135, 135}, {1, 750, 750}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ {75ms,
+ {{0, 135, 135, .isResampled = true}, {1, 750, 750, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE},
};
consumeInputEventEntries(expectedEntries, frameTime);
@@ -554,7 +569,7 @@ TEST_F(TouchResamplingTest, TwoPointersAreResampledIndependently) {
* The latest event with ACTION_MOVE was at t = 70, coord = 700.
* Use that value for resampling here: (600 - 700) / (90 - 70) * 5 + 600
*/
- {95ms, {{1, 575, 575}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ {95ms, {{1, 575, 575, .isResampled = true}}, AMOTION_EVENT_ACTION_MOVE},
};
consumeInputEventEntries(expectedEntries, frameTime);
}