Merge changes from topic "resampling for multiple pointers"
* changes:
Fix resampling for multiple pointers
Fix broken input tests
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 9449474..ea1d2aa 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -381,6 +381,18 @@
}
}
+ void initializeFrom(const History& other) {
+ eventTime = other.eventTime;
+ idBits = other.idBits; // temporary copy
+ for (size_t i = 0; i < other.idBits.count(); i++) {
+ uint32_t id = idBits.clearFirstMarkedBit();
+ int32_t index = other.idToIndex[id];
+ idToIndex[id] = index;
+ pointers[index].copyFrom(other.pointers[index]);
+ }
+ idBits = other.idBits; // final copy
+ }
+
const PointerCoords& getPointerById(uint32_t id) const {
return pointers[idToIndex[id]];
}
@@ -455,7 +467,6 @@
int32_t* displayId);
void updateTouchState(InputMessage& msg);
- bool rewriteMessage(const TouchState& state, InputMessage& msg);
void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
const InputMessage *next);
@@ -464,6 +475,7 @@
status_t sendUnchainedFinishedSignal(uint32_t seq, bool handled);
+ static void rewriteMessage(TouchState& state, InputMessage& msg);
static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg);
static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg);
static void addSample(MotionEvent* event, const InputMessage* msg);
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 9abd04c..905d336 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -614,10 +614,7 @@
if (index >= 0) {
TouchState& touchState = mTouchStates.editItemAt(index);
touchState.addHistory(msg);
- bool messageRewritten = rewriteMessage(touchState, msg);
- if (!messageRewritten) {
- touchState.lastResample.idBits.clear();
- }
+ rewriteMessage(touchState, msg);
}
break;
}
@@ -645,7 +642,7 @@
case AMOTION_EVENT_ACTION_SCROLL: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- const TouchState& touchState = mTouchStates.itemAt(index);
+ TouchState& touchState = mTouchStates.editItemAt(index);
rewriteMessage(touchState, msg);
}
break;
@@ -655,7 +652,7 @@
case AMOTION_EVENT_ACTION_CANCEL: {
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
- const TouchState& touchState = mTouchStates.itemAt(index);
+ TouchState& touchState = mTouchStates.editItemAt(index);
rewriteMessage(touchState, msg);
mTouchStates.removeAt(index);
}
@@ -664,28 +661,38 @@
}
}
-bool InputConsumer::rewriteMessage(const TouchState& state, InputMessage& msg) {
- bool messageRewritten = false;
+/**
+ * Replace the coordinates in msg with the coordinates in lastResample, if necessary.
+ *
+ * If lastResample is no longer valid for a specific pointer (i.e. the lastResample time
+ * is in the past relative to msg and the past two events do not contain identical coordinates),
+ * then invalidate the lastResample data for that pointer.
+ * If the two past events have identical coordinates, then lastResample data for that pointer will
+ * remain valid, and will be used to replace these coordinates. Thus, if a certain coordinate x0 is
+ * resampled to the new value x1, then x1 will always be used to replace x0 until some new value
+ * not equal to x0 is received.
+ */
+void InputConsumer::rewriteMessage(TouchState& state, InputMessage& msg) {
nsecs_t eventTime = msg.body.motion.eventTime;
for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
uint32_t id = msg.body.motion.pointers[i].properties.id;
if (state.lastResample.idBits.hasBit(id)) {
- PointerCoords& msgCoords = msg.body.motion.pointers[i].coords;
- const PointerCoords& resampleCoords = state.lastResample.getPointerById(id);
if (eventTime < state.lastResample.eventTime ||
state.recentCoordinatesAreIdentical(id)) {
- msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
- msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
+ PointerCoords& msgCoords = msg.body.motion.pointers[i].coords;
+ const PointerCoords& resampleCoords = state.lastResample.getPointerById(id);
#if DEBUG_RESAMPLING
ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
resampleCoords.getX(), resampleCoords.getY(),
msgCoords.getX(), msgCoords.getY());
#endif
- messageRewritten = true;
+ msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
+ msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
+ } else {
+ state.lastResample.idBits.clearBit(id);
}
}
}
- return messageRewritten;
}
void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
@@ -713,7 +720,6 @@
}
// Ensure that the current sample has all of the pointers that need to be reported.
- // Also ensure that the past two "real" touch events do not contain duplicate coordinates
const History* current = touchState.getHistory(0);
size_t pointerCount = event->getPointerCount();
for (size_t i = 0; i < pointerCount; i++) {
@@ -724,12 +730,6 @@
#endif
return;
}
- if (touchState.recentCoordinatesAreIdentical(id)) {
-#if DEBUG_RESAMPLING
- ALOGD("Not resampled, past two historical events have duplicate coordinates");
-#endif
- return;
- }
}
// Find the data to use for resampling.
@@ -783,18 +783,32 @@
}
// Resample touch coordinates.
+ History oldLastResample;
+ oldLastResample.initializeFrom(touchState.lastResample);
touchState.lastResample.eventTime = sampleTime;
touchState.lastResample.idBits.clear();
for (size_t i = 0; i < pointerCount; i++) {
uint32_t id = event->getPointerId(i);
touchState.lastResample.idToIndex[id] = i;
touchState.lastResample.idBits.markBit(id);
+ if (oldLastResample.hasPointerId(id) && touchState.recentCoordinatesAreIdentical(id)) {
+ // 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.
+
+ // 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
+ // lastResample in place becasue the mapping from pointer ID to index may have changed.
+ touchState.lastResample.pointers[i].copyFrom(oldLastResample.getPointerById(id));
+ continue;
+ }
+
PointerCoords& resampledCoords = touchState.lastResample.pointers[i];
const PointerCoords& currentCoords = current->getPointerById(id);
+ resampledCoords.copyFrom(currentCoords);
if (other->idBits.hasBit(id)
&& shouldResampleTool(event->getToolType(i))) {
const PointerCoords& otherCoords = other->getPointerById(id);
- resampledCoords.copyFrom(currentCoords);
resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
lerp(currentCoords.getX(), otherCoords.getX(), alpha));
resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
@@ -808,7 +822,6 @@
alpha);
#endif
} else {
- resampledCoords.copyFrom(currentCoords);
#if DEBUG_RESAMPLING
ALOGD("[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f)",
id, resampledCoords.getX(), resampledCoords.getY(),
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 0028655..8137e3d 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -9,8 +9,8 @@
],
cflags: [
"-Wall",
+ "-Wextra",
"-Werror",
- "-Wno-error=sign-compare", // to fix later
"-Wno-unused-variable",
],
shared_libs: [
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 3fb1c6d..fd3b7c8 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -184,7 +184,7 @@
ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType());
ASSERT_EQ(2, event.getDeviceId());
- ASSERT_EQ(AINPUT_SOURCE_GAMEPAD, event.getSource());
+ ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_GAMEPAD), event.getSource());
ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, event.getAction());
ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, event.getFlags());
ASSERT_EQ(AKEYCODE_BUTTON_X, event.getKeyCode());
@@ -196,7 +196,7 @@
// Set source.
event.setSource(AINPUT_SOURCE_JOYSTICK);
- ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource());
+ ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource());
}
@@ -300,7 +300,7 @@
// Check properties.
ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
ASSERT_EQ(2, event->getDeviceId());
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource());
+ ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_TOUCHSCREEN), event->getSource());
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction());
ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags());
ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
@@ -432,7 +432,7 @@
// Set source.
event.setSource(AINPUT_SOURCE_JOYSTICK);
- ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource());
+ ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource());
// Set action.
event.setAction(AMOTION_EVENT_ACTION_CANCEL);
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index a136738..34c52d0 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -89,8 +89,9 @@
uint32_t consumeSeq;
InputEvent* event;
+ int32_t displayId;
status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
- 0);
+ &displayId);
ASSERT_EQ(OK, status)
<< "consumer consume should return OK";
@@ -133,7 +134,7 @@
const uint32_t seq = 15;
const int32_t deviceId = 1;
const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
- const int32_t displayId = 0;
+ int32_t displayId = 0;
const int32_t action = AMOTION_EVENT_ACTION_MOVE;
const int32_t actionButton = 0;
const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
@@ -176,7 +177,7 @@
uint32_t consumeSeq;
InputEvent* event;
status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
- 0);
+ &displayId);
ASSERT_EQ(OK, status)
<< "consumer consume should return OK";
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 98e135d..48fd0cf 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -1992,10 +1992,10 @@
const PointerCoords* usingCoords = motionEntry->pointerCoords;
// Set the X and Y offset depending on the input source.
- float xOffset, yOffset, scaleFactor;
+ float xOffset, yOffset;
if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
&& !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
- scaleFactor = dispatchEntry->scaleFactor;
+ float scaleFactor = dispatchEntry->scaleFactor;
xOffset = dispatchEntry->xOffset * scaleFactor;
yOffset = dispatchEntry->yOffset * scaleFactor;
if (scaleFactor != 1.0f) {
@@ -2008,7 +2008,6 @@
} else {
xOffset = 0.0f;
yOffset = 0.0f;
- scaleFactor = 1.0f;
// We don't want the dispatch target to know.
if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 420d06b..9aef5b8 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -2260,7 +2260,7 @@
dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
dump.appendFormat(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
- dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime);
+ dump.appendFormat(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
}
@@ -2621,7 +2621,7 @@
dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
- dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime);
+ dump.appendFormat(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
}
void CursorInputMapper::configure(nsecs_t when,
@@ -5510,18 +5510,15 @@
// Otherwise choose an arbitrary remaining pointer.
// This guarantees we always have an active touch id when there is at least one pointer.
// We keep the same active touch id for as long as possible.
- bool activeTouchChanged = false;
int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
int32_t activeTouchId = lastActiveTouchId;
if (activeTouchId < 0) {
if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
- activeTouchChanged = true;
activeTouchId = mPointerGesture.activeTouchId =
mCurrentCookedState.fingerIdBits.firstMarkedBit();
mPointerGesture.firstTouchTime = when;
}
} else if (!mCurrentCookedState.fingerIdBits.hasBit(activeTouchId)) {
- activeTouchChanged = true;
if (!mCurrentCookedState.fingerIdBits.isEmpty()) {
activeTouchId = mPointerGesture.activeTouchId =
mCurrentCookedState.fingerIdBits.firstMarkedBit();
@@ -5617,7 +5614,6 @@
}
if (bestId >= 0 && bestId != activeTouchId) {
mPointerGesture.activeTouchId = activeTouchId = bestId;
- activeTouchChanged = true;
#if DEBUG_GESTURES
ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
"bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);