From 38c992841b5f6bc80359dbf60d31aa7b994160fc Mon Sep 17 00:00:00 2001 From: Svetoslav Ganov Date: Tue, 3 Sep 2013 09:24:48 -0700 Subject: [PATCH] Crashes in TouchExplorer on two finger swipe. 1. The logic for finding the active pointer was incorrect. The code was iterating over all pointer ids and taking the minimum, i.e. the pointer that first went down. The problem was that the down time for pointers that are not down was also considered (set to zero), thus sometimes we would consider the first pointer that went down to be a pointer that is not down at all. Now we are iterating only over the pointers that are down. 2. The batched events while waiting to see if the user is exploring or gesturing were added even if we were in touch exploration state at which point we do not have to batch. As a result we ended up having lefovers from a previous gesture when handling the delayed events and crash. bug:10312546 Change-Id: I4728541ac12e4da4577d22e4314101dd169a52fb --- .../server/accessibility/TouchExplorer.java | 36 +++++++++++++--------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java index 8fb3998f4859..1b8876d745c0 100644 --- a/services/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/java/com/android/server/accessibility/TouchExplorer.java @@ -417,9 +417,6 @@ class TouchExplorer implements EventStreamTransformation { mSendTouchInteractionEndDelayed.forceSendAndRemove(); } - // Cache the event until we discern exploration from gesturing. - mSendHoverEnterAndMoveDelayed.addEvent(event); - // If we have the first tap, schedule a long press and break // since we do not want to schedule hover enter because // the delayed callback will kick in before the long click. @@ -432,11 +429,16 @@ class TouchExplorer implements EventStreamTransformation { break; } if (!mTouchExplorationInProgress) { - // Deliver hover enter with a delay to have a chance - // to detect what the user is trying to do. - final int pointerId = receivedTracker.getPrimaryPointerId(); - final int pointerIdBits = (1 << pointerId); - mSendHoverEnterAndMoveDelayed.post(event, true, pointerIdBits, policyFlags); + if (!mSendHoverEnterAndMoveDelayed.isPending()) { + // Deliver hover enter with a delay to have a chance + // to detect what the user is trying to do. + final int pointerId = receivedTracker.getPrimaryPointerId(); + final int pointerIdBits = (1 << pointerId); + mSendHoverEnterAndMoveDelayed.post(event, true, pointerIdBits, + policyFlags); + } + // Cache the event until we discern exploration from gesturing. + mSendHoverEnterAndMoveDelayed.addEvent(event); } } break; case MotionEvent.ACTION_POINTER_DOWN: { @@ -1719,7 +1721,7 @@ class TouchExplorer implements EventStreamTransformation { } break; } if (DEBUG) { - Slog.i(LOG_TAG_RECEIVED_POINTER_TRACKER, "Received pointer: " + toString()); + Slog.i(LOG_TAG_RECEIVED_POINTER_TRACKER, "Received pointer:\n" + toString()); } } @@ -1777,7 +1779,7 @@ class TouchExplorer implements EventStreamTransformation { */ public int getPrimaryPointerId() { if (mPrimaryPointerId == INVALID_POINTER_ID) { - mPrimaryPointerId = findPrimaryPointer(); + mPrimaryPointerId = findPrimaryPointerId(); } return mPrimaryPointerId; } @@ -1861,17 +1863,21 @@ class TouchExplorer implements EventStreamTransformation { } /** - * @return The primary pointer. + * @return The primary pointer id. */ - private int findPrimaryPointer() { + private int findPrimaryPointerId() { int primaryPointerId = INVALID_POINTER_ID; long minDownTime = Long.MAX_VALUE; + // Find the pointer that went down first. - for (int i = 0, count = mReceivedPointerDownTime.length; i < count; i++) { - final long downPointerTime = mReceivedPointerDownTime[i]; + int pointerIdBits = mReceivedPointersDown; + while (pointerIdBits > 0) { + final int pointerId = Integer.numberOfTrailingZeros(pointerIdBits); + pointerIdBits &= ~(1 << pointerId); + final long downPointerTime = mReceivedPointerDownTime[pointerId]; if (downPointerTime < minDownTime) { minDownTime = downPointerTime; - primaryPointerId = i; + primaryPointerId = pointerId; } } return primaryPointerId; -- 2.11.0