Only allow touch events from one device at a time.
Reject movements from other devices when one device is already down.
This fixes jittery behavior when the user moves the mouse and touches
the screen at the same time.
Change-Id: I99151c8f2596a3139720f776bcbc559d4b314878
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 3675021..89a7751 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -1060,14 +1060,26 @@
// Update the touch state as needed based on the properties of the touch event.
int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
+ bool isSplit, wrongDevice;
if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
mTempTouchState.reset();
mTempTouchState.down = true;
+ mTempTouchState.deviceId = entry->deviceId;
+ isSplit = false;
+ wrongDevice = false;
} else {
mTempTouchState.copyFrom(mTouchState);
+ isSplit = mTempTouchState.split;
+ wrongDevice = mTempTouchState.down && mTempTouchState.deviceId != entry->deviceId;
+ if (wrongDevice) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+ LOGD("Dropping event because a pointer for a different device is already down.");
+#endif
+ injectionResult = INPUT_EVENT_INJECTION_FAILED;
+ goto Failed;
+ }
}
- bool isSplit = mTempTouchState.split && mTempTouchState.down;
if (maskedAction == AMOTION_EVENT_ACTION_DOWN
|| (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
/* Case 1: New splittable pointer going down. */
@@ -1279,39 +1291,41 @@
// Update final pieces of touch state if the injector had permission.
if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
- if (maskedAction == AMOTION_EVENT_ACTION_UP
- || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
- // All pointers up or canceled.
- mTempTouchState.reset();
- } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- // First pointer went down.
- if (mTouchState.down) {
+ if (!wrongDevice) {
+ if (maskedAction == AMOTION_EVENT_ACTION_UP
+ || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
+ // All pointers up or canceled.
+ mTempTouchState.reset();
+ } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
+ // First pointer went down.
+ if (mTouchState.down) {
#if DEBUG_FOCUS
- LOGD("Pointer down received while already down.");
+ LOGD("Pointer down received while already down.");
#endif
- }
- } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
- // One pointer went up.
- if (isSplit) {
- int32_t pointerIndex = getMotionEventActionPointerIndex(action);
- uint32_t pointerId = entry->pointerIds[pointerIndex];
+ }
+ } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
+ // One pointer went up.
+ if (isSplit) {
+ int32_t pointerIndex = getMotionEventActionPointerIndex(action);
+ uint32_t pointerId = entry->pointerIds[pointerIndex];
- for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
- TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
- if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
- touchedWindow.pointerIds.clearBit(pointerId);
- if (touchedWindow.pointerIds.isEmpty()) {
- mTempTouchState.windows.removeAt(i);
- continue;
+ for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
+ TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
+ if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
+ touchedWindow.pointerIds.clearBit(pointerId);
+ if (touchedWindow.pointerIds.isEmpty()) {
+ mTempTouchState.windows.removeAt(i);
+ continue;
+ }
}
+ i += 1;
}
- i += 1;
}
}
- }
- // Save changes to touch state.
- mTouchState.copyFrom(mTempTouchState);
+ // Save changes to touch state.
+ mTouchState.copyFrom(mTempTouchState);
+ }
} else {
#if DEBUG_FOCUS
LOGD("Not updating touch focus because injection was denied.");
@@ -2768,6 +2782,7 @@
dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
+ dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId);
if (!mTouchState.windows.isEmpty()) {
dump.append(INDENT "TouchedWindows:\n");
for (size_t i = 0; i < mTouchState.windows.size(); i++) {
@@ -3642,7 +3657,7 @@
// --- InputDispatcher::TouchState ---
InputDispatcher::TouchState::TouchState() :
- down(false), split(false) {
+ down(false), split(false), deviceId(-1) {
}
InputDispatcher::TouchState::~TouchState() {
@@ -3651,12 +3666,14 @@
void InputDispatcher::TouchState::reset() {
down = false;
split = false;
+ deviceId = -1;
windows.clear();
}
void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
down = other.down;
split = other.split;
+ deviceId = other.deviceId;
windows.clear();
windows.appendVector(other.windows);
}