OSDN Git Service

Crashes in TouchExplorer on two finger swipe.
authorSvetoslav Ganov <svetoslavganov@google.com>
Tue, 3 Sep 2013 16:24:48 +0000 (09:24 -0700)
committerSvetoslav Ganov <svetoslavganov@google.com>
Tue, 3 Sep 2013 16:24:52 +0000 (09:24 -0700)
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

services/java/com/android/server/accessibility/TouchExplorer.java

index 8fb3998..1b8876d 100644 (file)
@@ -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;