Touch pad improvements.
Bug: 4124987
Only show one spot per touch point instead of one spot per
finger for multitouch gestures.
Tweaked the pointer acceleration curves.
Dissociated the hover/tap timeouts from the "tap" timeout
since they mean very different things.
Change-Id: I7c2cbd30feeb65ebc12f6c7e33a67dc9a9f59d4c
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index a22ec1c..36a5f89 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -36,6 +36,12 @@
// Log debug messages about gesture detection.
#define DEBUG_GESTURES 0
+// Specifies whether spots follow fingers or touch points.
+// If 1, show exactly one spot per finger in multitouch gestures.
+// If 0, show exactly one spot per generated touch point in multitouch gestures, so the
+// spots indicate exactly which points on screen are being touched.
+#define SPOT_FOLLOWS_FINGER 0
+
#include "InputReader.h"
#include <cutils/atomic.h>
@@ -186,23 +192,6 @@
return edgeFlags;
}
-static void clampPositionUsingPointerBounds(
- const sp<PointerControllerInterface>& pointerController, float* x, float* y) {
- float minX, minY, maxX, maxY;
- if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
- if (*x < minX) {
- *x = minX;
- } else if (*x > maxX) {
- *x = maxX;
- }
- if (*y < minY) {
- *y = minY;
- } else if (*y > maxY) {
- *y = maxY;
- }
- }
-}
-
static float calculateCommonVector(float a, float b) {
if (a > 0 && b > 0) {
return a < b ? a : b;
@@ -746,8 +735,8 @@
mConfig.pointerGestureTapSlop);
dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
- dump.appendFormat(INDENT3 "MultitouchMinSpeed: %0.1fpx/s\n",
- mConfig.pointerGestureMultitouchMinSpeed);
+ dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
+ mConfig.pointerGestureMultitouchMinDistance);
dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
mConfig.pointerGestureSwipeTransitionAngleCosine);
dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
@@ -3291,11 +3280,18 @@
cancelPreviousGesture = false;
}
- // Switch pointer presentation.
- mPointerController->setPresentation(
- mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
- ? PointerControllerInterface::PRESENTATION_SPOT
- : PointerControllerInterface::PRESENTATION_POINTER);
+ // Update the pointer presentation and spots.
+ if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
+ mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
+ if (finishPreviousGesture || cancelPreviousGesture) {
+ mPointerController->clearSpots();
+ }
+ mPointerController->setSpots(mPointerGesture.spotGesture,
+ mPointerGesture.spotCoords, mPointerGesture.spotIdToIndex,
+ mPointerGesture.spotIdBits);
+ } else {
+ mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
+ }
// Show or hide the pointer if needed.
switch (mPointerGesture.currentGestureMode) {
@@ -3484,7 +3480,6 @@
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
mPointerGesture.spotIdBits.clear();
- moveSpotsLocked();
}
return true;
}
@@ -3566,10 +3561,12 @@
if (isQuietTime) {
// Case 1: Quiet time. (QUIET)
#if DEBUG_GESTURES
- LOGD("Gestures: QUIET for next %0.3fms",
- (mPointerGesture.quietTime + QUIET_INTERVAL - when) * 0.000001f);
+ LOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
+ + mConfig->pointerGestureQuietInterval - when) * 0.000001f);
#endif
- *outFinishPreviousGesture = true;
+ if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
+ *outFinishPreviousGesture = true;
+ }
mPointerGesture.activeGestureId = -1;
mPointerGesture.currentGestureMode = PointerGesture::QUIET;
@@ -3580,7 +3577,6 @@
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
mPointerGesture.spotIdBits.clear();
- moveSpotsLocked();
}
} else if (isPointerDown(mCurrentTouch.buttonState)) {
// Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
@@ -3684,11 +3680,12 @@
mPointerGesture.spotIdToIndex[0] = 0;
mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
}
- moveSpotsLocked();
}
} else if (mCurrentTouch.pointerCount == 0) {
// Case 3. No fingers down and button is not pressed. (NEUTRAL)
- *outFinishPreviousGesture = true;
+ if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
+ *outFinishPreviousGesture = true;
+ }
// Watch for taps coming out of HOVER or TAP_DRAG mode.
// Checking for taps after TAP_DRAG allows us to detect double-taps.
@@ -3730,7 +3727,6 @@
mPointerGesture.spotIdBits.markBit(lastActiveTouchId);
mPointerGesture.spotIdToIndex[lastActiveTouchId] = 0;
mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
- moveSpotsLocked();
}
tapped = true;
@@ -3762,7 +3758,6 @@
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
mPointerGesture.spotIdBits.clear();
- moveSpotsLocked();
}
}
} else if (mCurrentTouch.pointerCount == 1) {
@@ -3826,7 +3821,9 @@
#if DEBUG_GESTURES
LOGD("Gestures: HOVER");
#endif
- *outFinishPreviousGesture = true;
+ if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
+ *outFinishPreviousGesture = true;
+ }
mPointerGesture.activeGestureId = 0;
down = false;
}
@@ -3857,7 +3854,6 @@
mPointerGesture.spotIdBits.markBit(activeTouchId);
mPointerGesture.spotIdToIndex[activeTouchId] = 0;
mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
- moveSpotsLocked();
}
} else {
// Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
@@ -3886,8 +3882,8 @@
// Reset the gesture.
#if DEBUG_GESTURES
LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
- "settle time remaining %0.3fms",
- (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
+ "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
+ + mConfig->pointerGestureMultitouchSettleInterval - when)
* 0.000001f);
#endif
*outCancelPreviousGesture = true;
@@ -3908,8 +3904,8 @@
// for the gesture. Other spots will be positioned relative to this one.
#if DEBUG_GESTURES
LOGD("Gestures: Using active spot as reference for MULTITOUCH, "
- "settle time expired %0.3fms ago",
- (when - mPointerGesture.firstTouchTime - MULTITOUCH_SETTLE_INTERVAL)
+ "settle time expired %0.3fms ago", (when - mPointerGesture.firstTouchTime
+ - mConfig->pointerGestureMultitouchSettleInterval)
* 0.000001f);
#endif
const PointerData& d = mLastTouch.pointers[mLastTouch.idToIndex[
@@ -3924,8 +3920,8 @@
// Use the centroid and pointer location as the reference points for the gesture.
#if DEBUG_GESTURES
LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
- "settle time remaining %0.3fms",
- (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
+ "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
+ + mConfig->pointerGestureMultitouchSettleInterval - when)
* 0.000001f);
#endif
mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
@@ -3935,68 +3931,121 @@
}
}
- if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
- float d;
- if (mCurrentTouch.pointerCount > 2) {
- // There are more than two pointers, switch to FREEFORM.
-#if DEBUG_GESTURES
- LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
- mCurrentTouch.pointerCount);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
- } else if (((d = distance(
- mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y,
- mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y))
- > mLocked.pointerGestureMaxSwipeWidth)) {
- // There are two pointers but they are too far apart, switch to FREEFORM.
-#if DEBUG_GESTURES
- LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
- d, mLocked.pointerGestureMaxSwipeWidth);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ // Clear the reference deltas for fingers not yet included in the reference calculation.
+ for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value);
+ !idBits.isEmpty(); ) {
+ uint32_t id = idBits.firstMarkedBit();
+ idBits.clearBit(id);
+
+ mPointerGesture.referenceDeltas[id].dx = 0;
+ mPointerGesture.referenceDeltas[id].dy = 0;
+ }
+ mPointerGesture.referenceIdBits = mCurrentTouch.idBits;
+
+ // Add delta for all fingers and calculate a common movement delta.
+ float commonDeltaX = 0, commonDeltaY = 0;
+ BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value);
+ for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
+ bool first = (idBits == commonIdBits);
+ uint32_t id = idBits.firstMarkedBit();
+ idBits.clearBit(id);
+
+ const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]];
+ const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]];
+ PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
+ delta.dx += cpd.x - lpd.x;
+ delta.dy += cpd.y - lpd.y;
+
+ if (first) {
+ commonDeltaX = delta.dx;
+ commonDeltaY = delta.dy;
} else {
- // There are two pointers. Wait for both pointers to start moving
- // before deciding whether this is a SWIPE or FREEFORM gesture.
- uint32_t id1 = mCurrentTouch.pointers[0].id;
- uint32_t id2 = mCurrentTouch.pointers[1].id;
+ commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
+ commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
+ }
+ }
- float vx1, vy1, vx2, vy2;
- mPointerGesture.velocityTracker.getVelocity(id1, &vx1, &vy1);
- mPointerGesture.velocityTracker.getVelocity(id2, &vx2, &vy2);
+ // Consider transitions from PRESS to SWIPE or MULTITOUCH.
+ if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
+ float dist[MAX_POINTER_ID + 1];
+ int32_t distOverThreshold = 0;
+ for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.firstMarkedBit();
+ idBits.clearBit(id);
- float speed1 = hypotf(vx1, vy1);
- float speed2 = hypotf(vx2, vy2);
- if (speed1 >= mConfig->pointerGestureMultitouchMinSpeed
- && speed2 >= mConfig->pointerGestureMultitouchMinSpeed) {
- // Calculate the dot product of the velocity vectors.
- // When the vectors are oriented in approximately the same direction,
- // the angle betweeen them is near zero and the cosine of the angle
- // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
- float dot = vx1 * vx2 + vy1 * vy2;
- float cosine = dot / (speed1 * speed2); // denominator always > 0
- if (cosine >= mConfig->pointerGestureSwipeTransitionAngleCosine) {
- // Pointers are moving in the same direction. Switch to SWIPE.
+ PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
+ dist[id] = hypotf(delta.dx * mLocked.pointerGestureXZoomScale,
+ delta.dy * mLocked.pointerGestureYZoomScale);
+ if (dist[id] > mConfig->pointerGestureMultitouchMinDistance) {
+ distOverThreshold += 1;
+ }
+ }
+
+ // Only transition when at least two pointers have moved further than
+ // the minimum distance threshold.
+ if (distOverThreshold >= 2) {
+ float d;
+ if (mCurrentTouch.pointerCount > 2) {
+ // There are more than two pointers, switch to FREEFORM.
#if DEBUG_GESTURES
- LOGD("Gestures: PRESS transitioned to SWIPE, "
- "speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, "
- "cosine %0.3f >= %0.3f",
- speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED,
- cosine, SWIPE_TRANSITION_ANGLE_COSINE);
+ LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
+ mCurrentTouch.pointerCount);
#endif
- mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
- } else {
- // Pointers are moving in different directions. Switch to FREEFORM.
+ *outCancelPreviousGesture = true;
+ mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ } else if (((d = distance(
+ mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y,
+ mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y))
+ > mLocked.pointerGestureMaxSwipeWidth)) {
+ // There are two pointers but they are too far apart for a SWIPE,
+ // switch to FREEFORM.
#if DEBUG_GESTURES
- LOGD("Gestures: PRESS transitioned to FREEFORM, "
- "speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, "
- "cosine %0.3f < %0.3f",
- speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED,
- cosine, SWIPE_TRANSITION_ANGLE_COSINE);
+ LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
+ d, mLocked.pointerGestureMaxSwipeWidth);
#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ *outCancelPreviousGesture = true;
+ mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ } else {
+ // There are two pointers. Wait for both pointers to start moving
+ // before deciding whether this is a SWIPE or FREEFORM gesture.
+ uint32_t id1 = mCurrentTouch.pointers[0].id;
+ uint32_t id2 = mCurrentTouch.pointers[1].id;
+ float dist1 = dist[id1];
+ float dist2 = dist[id2];
+ if (dist1 >= mConfig->pointerGestureMultitouchMinDistance
+ && dist2 >= mConfig->pointerGestureMultitouchMinDistance) {
+ // Calculate the dot product of the displacement vectors.
+ // When the vectors are oriented in approximately the same direction,
+ // the angle betweeen them is near zero and the cosine of the angle
+ // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
+ PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
+ PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
+ float dot = delta1.dx * delta2.dx + delta1.dy * delta2.dy;
+ float cosine = dot / (dist1 * dist2); // denominator always > 0
+ if (cosine >= mConfig->pointerGestureSwipeTransitionAngleCosine) {
+ // Pointers are moving in the same direction. Switch to SWIPE.
+#if DEBUG_GESTURES
+ LOGD("Gestures: PRESS transitioned to SWIPE, "
+ "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
+ "cosine %0.3f >= %0.3f",
+ dist1, mConfig->pointerGestureMultitouchMinDistance,
+ dist2, mConfig->pointerGestureMultitouchMinDistance,
+ cosine, mConfig->pointerGestureSwipeTransitionAngleCosine);
+#endif
+ mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
+ } else {
+ // Pointers are moving in different directions. Switch to FREEFORM.
+#if DEBUG_GESTURES
+ LOGD("Gestures: PRESS transitioned to FREEFORM, "
+ "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
+ "cosine %0.3f < %0.3f",
+ dist1, mConfig->pointerGestureMultitouchMinDistance,
+ dist2, mConfig->pointerGestureMultitouchMinDistance,
+ cosine, mConfig->pointerGestureSwipeTransitionAngleCosine);
+#endif
+ *outCancelPreviousGesture = true;
+ mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
+ }
}
}
}
@@ -4013,67 +4062,28 @@
}
}
- // Clear the reference deltas for fingers not yet included in the reference calculation.
- for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value);
- !idBits.isEmpty(); ) {
- uint32_t id = idBits.firstMarkedBit();
- idBits.clearBit(id);
-
- mPointerGesture.referenceDeltas[id].dx = 0;
- mPointerGesture.referenceDeltas[id].dy = 0;
- }
- mPointerGesture.referenceIdBits = mCurrentTouch.idBits;
-
- // Move the reference points based on the overall group motion of the fingers.
- // The objective is to calculate a vector delta that is common to the movement
- // of all fingers.
- BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value);
- if (!commonIdBits.isEmpty()) {
- float commonDeltaX = 0, commonDeltaY = 0;
- for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
- bool first = (idBits == commonIdBits);
+ // Move the reference points based on the overall group motion of the fingers
+ // except in PRESS mode while waiting for a transition to occur.
+ if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
+ && (commonDeltaX || commonDeltaY)) {
+ for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
uint32_t id = idBits.firstMarkedBit();
idBits.clearBit(id);
- const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]];
- const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]];
PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
- delta.dx += cpd.x - lpd.x;
- delta.dy += cpd.y - lpd.y;
-
- if (first) {
- commonDeltaX = delta.dx;
- commonDeltaY = delta.dy;
- } else {
- commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
- commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
- }
+ delta.dx = 0;
+ delta.dy = 0;
}
- if (commonDeltaX || commonDeltaY) {
- for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.firstMarkedBit();
- idBits.clearBit(id);
+ mPointerGesture.referenceTouchX += commonDeltaX;
+ mPointerGesture.referenceTouchY += commonDeltaY;
- PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
- delta.dx = 0;
- delta.dy = 0;
- }
+ commonDeltaX *= mLocked.pointerGestureXMovementScale;
+ commonDeltaY *= mLocked.pointerGestureYMovementScale;
+ mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
- mPointerGesture.referenceTouchX += commonDeltaX;
- mPointerGesture.referenceTouchY += commonDeltaY;
-
- commonDeltaX *= mLocked.pointerGestureXMovementScale;
- commonDeltaY *= mLocked.pointerGestureYMovementScale;
- mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
-
- mPointerGesture.referenceGestureX += commonDeltaX;
- mPointerGesture.referenceGestureY += commonDeltaY;
-
- clampPositionUsingPointerBounds(mPointerController,
- &mPointerGesture.referenceGestureX,
- &mPointerGesture.referenceGestureY);
- }
+ mPointerGesture.referenceGestureX += commonDeltaX;
+ mPointerGesture.referenceGestureY += commonDeltaY;
}
// Report gestures.
@@ -4225,9 +4235,10 @@
}
// Update spot locations for PRESS, SWIPE and FREEFORM.
- // We use the same calculation as we do to calculate the gesture pointers
- // for FREEFORM so that the spots smoothly track gestures.
if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
+#if SPOT_FOLLOWS_FINGER
+ // Use the same calculation as we do to calculate the gesture pointers
+ // for FREEFORM so that the spots smoothly track fingers across gestures.
mPointerGesture.spotIdBits.clear();
for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
uint32_t id = mCurrentTouch.pointers[i].id;
@@ -4244,7 +4255,19 @@
mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
}
- moveSpotsLocked();
+#else
+ // Show one spot per generated touch point.
+ // This may cause apparent discontinuities in spot motion when transitioning
+ // from PRESS to FREEFORM.
+ mPointerGesture.spotIdBits = mPointerGesture.currentGestureIdBits;
+ for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
+ uint32_t id = idBits.firstMarkedBit();
+ idBits.clearBit(id);
+ uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
+ mPointerGesture.spotIdToIndex[id] = index;
+ mPointerGesture.spotCoords[index] = mPointerGesture.currentGestureCoords[index];
+ }
+#endif
}
}
@@ -4281,11 +4304,6 @@
return true;
}
-void TouchInputMapper::moveSpotsLocked() {
- mPointerController->setSpots(mPointerGesture.spotGesture,
- mPointerGesture.spotCoords, mPointerGesture.spotIdToIndex, mPointerGesture.spotIdBits);
-}
-
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
int32_t action, int32_t flags, uint32_t metaState, int32_t edgeFlags,
const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits,