int32_t idToIndex[MAX_POINTER_ID + 1];
PointerCoords pointers[MAX_POINTERS];
- void initializeFrom(const InputMessage* msg) {
- eventTime = msg->body.motion.eventTime;
+ void initializeFrom(const InputMessage& msg) {
+ eventTime = msg.body.motion.eventTime;
idBits.clear();
- for (uint32_t i = 0; i < msg->body.motion.pointerCount; i++) {
- uint32_t id = msg->body.motion.pointers[i].properties.id;
+ for (uint32_t i = 0; i < msg.body.motion.pointerCount; i++) {
+ uint32_t id = msg.body.motion.pointers[i].properties.id;
idBits.markBit(id);
idToIndex[id] = i;
- pointers[i].copyFrom(msg->body.motion.pointers[i].coords);
+ pointers[i].copyFrom(msg.body.motion.pointers[i].coords);
}
}
lastResample.idBits.clear();
}
- void addHistory(const InputMessage* msg) {
+ void addHistory(const InputMessage& msg) {
historyCurrent ^= 1;
if (historySize < 2) {
historySize += 1;
const History* getHistory(size_t index) const {
return &history[(historyCurrent + index) & 1];
}
+
+ bool recentCoordinatesAreIdentical(uint32_t id) const {
+ // Return true if the two most recently received "raw" coordinates are identical
+ if (historySize < 2) {
+ return false;
+ }
+ float currentX = getHistory(0)->getPointerById(id).getX();
+ float currentY = getHistory(0)->getPointerById(id).getY();
+ float previousX = getHistory(1)->getPointerById(id).getX();
+ float previousY = getHistory(1)->getPointerById(id).getY();
+ if (currentX == previousX && currentY == previousY) {
+ return true;
+ }
+ return false;
+ }
};
Vector<TouchState> mTouchStates;
Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent,
int32_t* displayId);
- void updateTouchState(InputMessage* msg);
- void rewriteMessage(const TouchState& state, InputMessage* msg);
+ void updateTouchState(InputMessage& msg);
+ bool rewriteMessage(const TouchState& state, InputMessage& msg);
void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
const InputMessage *next);
MotionEvent* motionEvent = factory->createMotionEvent();
if (! motionEvent) return NO_MEMORY;
- updateTouchState(&mMsg);
+ updateTouchState(mMsg);
initializeMotionEvent(motionEvent, &mMsg);
*outSeq = mMsg.body.motion.seq;
*outEvent = motionEvent;
uint32_t chain = 0;
for (size_t i = 0; i < count; i++) {
InputMessage& msg = batch.samples.editItemAt(i);
- updateTouchState(&msg);
+ updateTouchState(msg);
if (i) {
SeqChain seqChain;
seqChain.seq = msg.body.motion.seq;
return OK;
}
-void InputConsumer::updateTouchState(InputMessage* msg) {
+void InputConsumer::updateTouchState(InputMessage& msg) {
if (!mResampleTouch ||
- !(msg->body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
+ !(msg.body.motion.source & AINPUT_SOURCE_CLASS_POINTER)) {
return;
}
- int32_t deviceId = msg->body.motion.deviceId;
- int32_t source = msg->body.motion.source;
- nsecs_t eventTime = msg->body.motion.eventTime;
+ int32_t deviceId = msg.body.motion.deviceId;
+ int32_t source = msg.body.motion.source;
// Update the touch state history to incorporate the new input message.
// If the message is in the past relative to the most recently produced resampled
// touch, then use the resampled time and coordinates instead.
- switch (msg->body.motion.action & AMOTION_EVENT_ACTION_MASK) {
+ switch (msg.body.motion.action & AMOTION_EVENT_ACTION_MASK) {
case AMOTION_EVENT_ACTION_DOWN: {
ssize_t index = findTouchState(deviceId, source);
if (index < 0) {
if (index >= 0) {
TouchState& touchState = mTouchStates.editItemAt(index);
touchState.addHistory(msg);
- if (eventTime < touchState.lastResample.eventTime) {
- rewriteMessage(touchState, msg);
- } else {
+ bool messageRewritten = rewriteMessage(touchState, msg);
+ if (!messageRewritten) {
touchState.lastResample.idBits.clear();
}
}
ssize_t index = findTouchState(deviceId, source);
if (index >= 0) {
TouchState& touchState = mTouchStates.editItemAt(index);
- touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
+ touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
rewriteMessage(touchState, msg);
}
break;
if (index >= 0) {
TouchState& touchState = mTouchStates.editItemAt(index);
rewriteMessage(touchState, msg);
- touchState.lastResample.idBits.clearBit(msg->body.motion.getActionId());
+ touchState.lastResample.idBits.clearBit(msg.body.motion.getActionId());
}
break;
}
}
}
-void InputConsumer::rewriteMessage(const TouchState& state, InputMessage* msg) {
- for (uint32_t i = 0; i < msg->body.motion.pointerCount; i++) {
- uint32_t id = msg->body.motion.pointers[i].properties.id;
+bool InputConsumer::rewriteMessage(const TouchState& state, InputMessage& msg) {
+ bool messageRewritten = false;
+ 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;
+ 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());
#if DEBUG_RESAMPLING
- ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
- resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
- resampleCoords.getAxisValue(AMOTION_EVENT_AXIS_Y),
- msgCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
- msgCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
+ ALOGD("[%d] - rewrite (%0.3f, %0.3f), old (%0.3f, %0.3f)", id,
+ resampleCoords.getX(), resampleCoords.getY(),
+ msgCoords.getX(), msgCoords.getY());
#endif
- msgCoords.setAxisValue(AMOTION_EVENT_AXIS_X, resampleCoords.getX());
- msgCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, resampleCoords.getY());
+ messageRewritten = true;
+ }
}
}
+ return messageRewritten;
}
void InputConsumer::resampleTouchState(nsecs_t sampleTime, MotionEvent* event,
}
// 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++) {
#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.
if (next) {
// Interpolate between current sample and future sample.
// So current->eventTime <= sampleTime <= future.eventTime.
- future.initializeFrom(next);
+ future.initializeFrom(*next);
other = &future;
nsecs_t delta = future.eventTime - current->eventTime;
if (delta < RESAMPLE_MIN_DELTA) {
#if DEBUG_RESAMPLING
- ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
+ ALOGD("Not resampled, delta time is too small: %" PRId64 " ns.", delta);
#endif
return;
}
nsecs_t delta = current->eventTime - other->eventTime;
if (delta < RESAMPLE_MIN_DELTA) {
#if DEBUG_RESAMPLING
- ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
+ ALOGD("Not resampled, delta time is too small: %" PRId64 " ns.", delta);
#endif
return;
} else if (delta > RESAMPLE_MAX_DELTA) {
#if DEBUG_RESAMPLING
- ALOGD("Not resampled, delta time is too large: %lld ns.", delta);
+ ALOGD("Not resampled, delta time is too large: %" PRId64 " ns.", delta);
#endif
return;
}
if (sampleTime > maxPredict) {
#if DEBUG_RESAMPLING
ALOGD("Sample time is too far in the future, adjusting prediction "
- "from %lld to %lld ns.",
+ "from %" PRId64 " to %" PRId64 " ns.",
sampleTime - current->eventTime, maxPredict - current->eventTime);
#endif
sampleTime = maxPredict;