summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/accessibility
diff options
context:
space:
mode:
authorSvetoslav Ganov <svetoslavganov@google.com>2011-08-26 20:33:33 -0700
committerSvetoslav Ganov <svetoslavganov@google.com>2011-08-29 00:06:57 -0700
commitf804420d6e37748b75478406e989c69303756980 (patch)
tree5e6f600ef08b2c9e26b71d918e8f1a70e00ec33d /services/java/com/android/server/accessibility
parentb8a9e15c2aa3d317834555244a90f184b46e1dcb (diff)
downloadframeworks_base-f804420d6e37748b75478406e989c69303756980.zip
frameworks_base-f804420d6e37748b75478406e989c69303756980.tar.gz
frameworks_base-f804420d6e37748b75478406e989c69303756980.tar.bz2
Clean up and bug fixes in the TouchExplorer.
1. The downTime of the first down event was zero but it should the event time. 2. Hover exit events were not injected while transitioning to delegating state and when tapping. 3. Differentiation between dragging and delagating state based on two moving pointer direction and distance is now based only on the direction. Hence, two pointers moving in the same direction are dragging, otherwise the event stream is delegated unmodified. The reason for that is the blind people cannot easily determine and control the distance between their fingers resulting in different behavior for gestures which the user thinks are the same which creates confusion. Also in some cases the delegation and draggig yield the same result, for example in list view, further adding to the confusion. This was also causing the status bar to be opened closed inreliably creating frustration. 4. Refactored the code such that now there is only one method that injects motion events and all request go through it. Some bugs were introduced by inconsistent implementation in the different injection methods. 5. Fixed a couple of event stream inconsistencies reported by the event consistency verifier. bug:5224183 bug:5223787 bug:5214829 Change-Id: I16c9be3562ad093017af5b974a41ab525b73453f
Diffstat (limited to 'services/java/com/android/server/accessibility')
-rw-r--r--services/java/com/android/server/accessibility/TouchExplorer.java298
1 files changed, 123 insertions, 175 deletions
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 4ad2916..496210c 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -21,11 +21,8 @@ import static android.view.accessibility.AccessibilityEvent.TYPE_TOUCH_EXPLORATI
import android.content.Context;
import android.os.Handler;
-import android.os.SystemClock;
import android.util.Slog;
import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
-import android.view.MotionEvent.PointerProperties;
import android.view.ViewConfiguration;
import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
@@ -75,11 +72,6 @@ public class TouchExplorer implements Explorer {
// Invalid pointer ID.
private static final int INVALID_POINTER_ID = -1;
- // The coefficient by which to multiply
- // ViewConfiguration.#getScaledTouchExplorationTapSlop()
- // to compute #mDraggingDistance.
- private static final int COEFFICIENT_DRAGGING_DISTANCE = 2;
-
// The time slop in milliseconds for activating an item after it has
// been touch explored. Tapping on an item within this slop will perform
// a click and tapping and holding down a long press.
@@ -95,23 +87,14 @@ public class TouchExplorer implements Explorer {
private static final float MIN_ANGLE_COS = 0.866025404f; // cos(pi/6)
// The delay for sending a hover enter event.
- private static final long DELAY_SEND_HOVER_MOVE = 200;
+ private static final long DELAY_SEND_HOVER_ENTER = 200;
+
+ // Constant referring to the ids bits of all pointers.
+ private static final int ALL_POINTER_ID_BITS = 0xFFFFFFFF;
// Temporary array for storing pointer IDs.
private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT];
- // Temporary array for storing PointerProperties
- private final PointerProperties[] mTempPointerProperties =
- PointerProperties.createArray(MAX_POINTER_COUNT);
-
- // Temporary array for storing PointerCoords
- private final PointerCoords[] mTempPointerCoords =
- PointerCoords.createArray(MAX_POINTER_COUNT);
-
- // The maximal distance between two pointers so they are
- // considered to be performing a drag operation.
- private final float mDraggingDistance;
-
// The distance from the last touch explored location tapping within
// which would perform a click and tapping and holding a long press.
private final int mTouchExplorationTapSlop;
@@ -159,7 +142,6 @@ public class TouchExplorer implements Explorer {
mInputFilter = inputFilter;
mTouchExplorationTapSlop =
ViewConfiguration.get(context).getScaledTouchExplorationTapSlop();
- mDraggingDistance = mTouchExplorationTapSlop * COEFFICIENT_DRAGGING_DISTANCE;
mPointerTracker = new PointerTracker(context);
mHandler = new Handler(context.getMainLooper());
mSendHoverDelayed = new SendHoverDelayed();
@@ -220,18 +202,21 @@ public class TouchExplorer implements Explorer {
+ "touch exploring state!");
}
case 1: {
- // Send hover if pending.
- mSendHoverDelayed.forceSendAndRemove();
+ mSendHoverDelayed.remove();
// Send a hover for every finger down so the user gets feedback.
final int pointerId = pointerTracker.getPrimaryActivePointerId();
final int pointerIdBits = (1 << pointerId);
final int lastAction = pointerTracker.getLastInjectedHoverAction();
- // If a hover enter for another pointer is delivered we send move.
- final int action = (lastAction == MotionEvent.ACTION_HOVER_ENTER)
- ? MotionEvent.ACTION_HOVER_MOVE
- : MotionEvent.ACTION_HOVER_ENTER;
- mSendHoverDelayed.post(event, action, pointerIdBits, policyFlags,
- DELAY_SEND_HOVER_MOVE);
+
+ // Deliver hover enter with a delay to have a change to detect
+ // whether the user actually starts a scrolling gesture.
+ if (lastAction == MotionEvent.ACTION_HOVER_EXIT) {
+ mSendHoverDelayed.post(event, MotionEvent.ACTION_HOVER_ENTER,
+ pointerIdBits, policyFlags, DELAY_SEND_HOVER_ENTER);
+ } else {
+ sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits,
+ policyFlags);
+ }
if (mLastTouchExploreEvent == null) {
break;
@@ -318,12 +303,11 @@ public class TouchExplorer implements Explorer {
}
} break;
case 2: {
- mSendHoverDelayed.forceSendAndRemove();
+ mSendHoverDelayed.remove();
mPerformLongPressDelayed.remove();
// We want to no longer hover over the location so subsequent
// touch at the same spot will generate a hover enter.
- sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
- policyFlags);
+ ensureHoverExitSent(event, pointerIdBits, policyFlags);
if (isDraggingGesture(event)) {
// Two pointers moving in the same direction within
@@ -340,6 +324,7 @@ public class TouchExplorer implements Explorer {
} else {
// Two pointers moving arbitrary are delegated to the view hierarchy.
mCurrentState = STATE_DELEGATING;
+ mSendHoverDelayed.remove();
if (mTouchExploreGestureInProgress) {
sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END);
mTouchExploreGestureInProgress = false;
@@ -349,12 +334,11 @@ public class TouchExplorer implements Explorer {
}
} break;
default: {
- mSendHoverDelayed.forceSendAndRemove();
+ mSendHoverDelayed.remove();
mPerformLongPressDelayed.remove();
// We want to no longer hover over the location so subsequent
// touch at the same spot will generate a hover enter.
- sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
- policyFlags);
+ ensureHoverExitSent(event, pointerIdBits, policyFlags);
// More than two pointers are delegated to the view hierarchy.
mCurrentState = STATE_DELEGATING;
@@ -379,8 +363,9 @@ public class TouchExplorer implements Explorer {
break;
}
- mSendHoverDelayed.forceSendAndRemove();
mPerformLongPressDelayed.remove();
+ mSendHoverDelayed.forceSendAndRemove();
+ ensureHoverExitSent(event, pointerIdBits, policyFlags);
// If touch exploring announce the end of the gesture.
// Also do not click on the last explored location.
@@ -388,11 +373,6 @@ public class TouchExplorer implements Explorer {
mTouchExploreGestureInProgress = false;
mLastTouchExploreEvent = MotionEvent.obtain(event);
sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END);
- final int lastAction = mPointerTracker.getLastInjectedHoverAction();
- if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
- sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
- pointerIdBits, policyFlags);
- }
break;
}
@@ -404,11 +384,6 @@ public class TouchExplorer implements Explorer {
final long exploreTime = mLastTouchExploreEvent.getEventTime();
final long deltaTime = eventTime - exploreTime;
if (deltaTime > ACTIVATION_TIME_SLOP) {
- final int lastAction = mPointerTracker.getLastInjectedHoverAction();
- if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
- sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
- pointerIdBits, policyFlags);
- }
mLastTouchExploreEvent = MotionEvent.obtain(event);
break;
}
@@ -421,11 +396,6 @@ public class TouchExplorer implements Explorer {
- event.getY(pointerIndex);
final float deltaMove = (float) Math.hypot(deltaX, deltaY);
if (deltaMove > mTouchExplorationTapSlop) {
- final int lastAction = mPointerTracker.getLastInjectedHoverAction();
- if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
- sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
- pointerIdBits, policyFlags);
- }
mLastTouchExploreEvent = MotionEvent.obtain(event);
break;
}
@@ -434,12 +404,6 @@ public class TouchExplorer implements Explorer {
sendActionDownAndUp(mLastTouchExploreEvent, policyFlags);
mLastTouchExploreEvent = null;
} else {
- mSendHoverDelayed.forceSendAndRemove();
- final int lastAction = mPointerTracker.getLastInjectedHoverAction();
- if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
- sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
- pointerIdBits, policyFlags);
- }
mLastTouchExploreEvent = MotionEvent.obtain(event);
}
} break;
@@ -448,13 +412,9 @@ public class TouchExplorer implements Explorer {
case MotionEvent.ACTION_CANCEL: {
mSendHoverDelayed.remove();
mPerformLongPressDelayed.remove();
- final int lastAction = pointerTracker.getLastInjectedHoverAction();
- if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
- final int pointerId = pointerTracker.getPrimaryActivePointerId();
- final int pointerIdBits = (1 << pointerId);
- sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
- policyFlags);
- }
+ final int pointerId = pointerTracker.getPrimaryActivePointerId();
+ final int pointerIdBits = (1 << pointerId);
+ ensureHoverExitSent(event, pointerIdBits, policyFlags);
clear();
} break;
}
@@ -540,7 +500,8 @@ public class TouchExplorer implements Explorer {
// a given distance and if such exist send them to the view hierarchy
final int notInjectedCount = mPointerTracker.getNotInjectedActivePointerCount();
if (notInjectedCount > 0) {
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ MotionEvent prototype = MotionEvent.obtain(event);
+ sendDownForAllActiveNotInjectedPointers(prototype, policyFlags);
}
} break;
case MotionEvent.ACTION_POINTER_UP: {
@@ -565,42 +526,47 @@ public class TouchExplorer implements Explorer {
* @param policyFlags The policy flags associated with the event.
*/
private void sendDownForAllActiveNotInjectedPointers(MotionEvent prototype, int policyFlags) {
- final PointerProperties[] pointerProperties = mTempPointerProperties;
- final PointerCoords[] pointerCoords = mTempPointerCoords;
final PointerTracker pointerTracker = mPointerTracker;
- int pointerDataIndex = 0;
+ int pointerIdBits = 0;
+ final int pointerCount = prototype.getPointerCount();
- final int pinterCount = prototype.getPointerCount();
- for (int i = 0; i < pinterCount; i++) {
+ // Find which pointers are already injected.
+ for (int i = 0; i < pointerCount; i++) {
final int pointerId = prototype.getPointerId(i);
+ if (pointerTracker.isInjectedPointerDown(pointerId)) {
+ pointerIdBits |= (1 << pointerId);
+ }
+ }
+ // Inject the active and not injected pointers.
+ for (int i = 0; i < pointerCount; i++) {
+ final int pointerId = prototype.getPointerId(i);
// Skip inactive pointers.
if (!pointerTracker.isActivePointer(pointerId)) {
continue;
}
- // Skip already delivered pointers.
+ // Do not send event for already delivered pointers.
if (pointerTracker.isInjectedPointerDown(pointerId)) {
continue;
}
+ pointerIdBits |= (1 << pointerId);
+ final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, i);
+ sendMotionEvent(prototype, action, pointerIdBits, policyFlags);
+ }
+ }
- // Populate and inject an event for the current pointer.
- prototype.getPointerProperties(i, pointerProperties[pointerDataIndex]);
- prototype.getPointerCoords(i, pointerCoords[pointerDataIndex]);
-
- final long downTime = pointerTracker.getLastInjectedDownEventTime();
- final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, pointerDataIndex);
- final int pointerCount = pointerDataIndex + 1;
- final long eventTime = SystemClock.uptimeMillis();
-
- MotionEvent event = MotionEvent.obtain(downTime, eventTime,
- action, pointerCount, pointerProperties, pointerCoords,
- prototype.getMetaState(), prototype.getButtonState(),
- prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
- prototype.getEdgeFlags(), prototype.getSource(), prototype.getFlags());
- sendMotionEvent(event, policyFlags);
- event.recycle();
-
- pointerDataIndex++;
+ /**
+ * Ensures that hover exit has been sent.
+ *
+ * @param prototype The prototype from which to create the injected events.
+ * @param pointerIdBits The bits of the pointers to send.
+ * @param policyFlags The policy flags associated with the event.
+ */
+ private void ensureHoverExitSent(MotionEvent prototype, int pointerIdBits, int policyFlags) {
+ final int lastAction = mPointerTracker.getLastInjectedHoverAction();
+ if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
+ sendMotionEvent(prototype, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
+ policyFlags);
}
}
@@ -613,38 +579,17 @@ public class TouchExplorer implements Explorer {
*/
private void sendUpForInjectedDownPointers(MotionEvent prototype, int policyFlags) {
final PointerTracker pointerTracker = mPointerTracker;
- final PointerProperties[] pointerProperties = mTempPointerProperties;
- final PointerCoords[] pointerCoords = mTempPointerCoords;
- int pointerDataIndex = 0;
-
- final int pointerCount = prototype.getPointerCount();
+ int pointerIdBits = 0;
+ final int pointerCount = prototype.getPointerCount();
for (int i = 0; i < pointerCount; i++) {
final int pointerId = prototype.getPointerId(i);
-
// Skip non injected down pointers.
if (!pointerTracker.isInjectedPointerDown(pointerId)) {
continue;
}
-
- // Populate and inject event.
- prototype.getPointerProperties(i, pointerProperties[pointerDataIndex]);
- prototype.getPointerCoords(i, pointerCoords[pointerDataIndex]);
-
- final long downTime = pointerTracker.getLastInjectedDownEventTime();
- final int action = computeInjectionAction(MotionEvent.ACTION_UP, pointerDataIndex);
- final int newPointerCount = pointerDataIndex + 1;
- final long eventTime = SystemClock.uptimeMillis();
-
- MotionEvent event = MotionEvent.obtain(downTime, eventTime, action,
- newPointerCount, pointerProperties, pointerCoords,
- prototype.getMetaState(), prototype.getButtonState(),
- prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
- prototype.getEdgeFlags(), prototype.getSource(), prototype.getFlags());
-
- sendMotionEvent(event, policyFlags);
- event.recycle();
-
- pointerDataIndex++;
+ pointerIdBits |= (1 << pointerId);
+ final int action = computeInjectionAction(MotionEvent.ACTION_UP, i);
+ sendMotionEvent(prototype, action, pointerIdBits, policyFlags);
}
}
@@ -659,7 +604,7 @@ public class TouchExplorer implements Explorer {
// All pointers active therefore we just inject the event as is.
if (prototype.getPointerCount() == pointerTracker.getActivePointerCount()) {
- sendMotionEvent(prototype, policyFlags);
+ sendMotionEvent(prototype, prototype.getAction(), ALL_POINTER_ID_BITS, policyFlags);
return;
}
@@ -670,20 +615,27 @@ public class TouchExplorer implements Explorer {
return;
}
+ // If the action pointer going up/down is not active we have nothing to do.
+ // However, for moves we keep going to report moves of active pointers.
+ final int actionMasked = prototype.getActionMasked();
+ final int actionPointerId = prototype.getPointerId(prototype.getActionIndex());
+ if (actionMasked != MotionEvent.ACTION_MOVE) {
+ if (!pointerTracker.isActiveOrWasLastActiveUpPointer(actionPointerId)) {
+ return;
+ }
+ }
+
+ // If the pointer is active or the pointer that just went up
+ // was active we keep the pointer data in the event.
int pointerIdBits = 0;
final int pointerCount = prototype.getPointerCount();
for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
final int pointerId = prototype.getPointerId(pointerIndex);
- // If the pointer is inactive or the pointer that just went up
- // was inactive we strip the pointer data from the event.
if (pointerTracker.isActiveOrWasLastActiveUpPointer(pointerId)) {
pointerIdBits |= (1 << pointerId);
}
}
-
- MotionEvent event = prototype.split(pointerIdBits);
- sendMotionEvent(event, policyFlags);
- event.recycle();
+ sendMotionEvent(prototype, prototype.getAction(), pointerIdBits, policyFlags);
}
/**
@@ -693,26 +645,11 @@ public class TouchExplorer implements Explorer {
* @param policyFlags The policy flags associated with the event.
*/
private void sendActionDownAndUp(MotionEvent prototype, int policyFlags) {
- final PointerProperties[] pointerProperties = mTempPointerProperties;
- final PointerCoords[] pointerCoords = mTempPointerCoords;
- final int pointerIndex = prototype.getActionIndex();
-
- // Send down.
- prototype.getPointerProperties(pointerIndex, pointerProperties[0]);
- prototype.getPointerCoords(pointerIndex, pointerCoords[0]);
-
- final long downTime = SystemClock.uptimeMillis();
- MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN,
- 1, pointerProperties, pointerCoords,
- prototype.getMetaState(), prototype.getButtonState(),
- prototype.getXPrecision(), prototype.getYPrecision(), prototype.getDeviceId(),
- prototype.getEdgeFlags(), prototype.getSource(), prototype.getFlags());
- sendMotionEvent(event, policyFlags);
-
- // Send up.
- event.setAction(MotionEvent.ACTION_UP);
- sendMotionEvent(event, policyFlags);
- event.recycle();
+ // Tap with the pointer that last went up - we may have inactive pointers.
+ final int pointerId = mPointerTracker.getLastReceivedUpPointerId();
+ final int pointerIdBits = (1 << pointerId);
+ sendMotionEvent(prototype, MotionEvent.ACTION_DOWN, pointerIdBits, policyFlags);
+ sendMotionEvent(prototype, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
}
/**
@@ -725,11 +662,33 @@ public class TouchExplorer implements Explorer {
*/
private void sendMotionEvent(MotionEvent prototype, int action, int pointerIdBits,
int policyFlags) {
- MotionEvent event = prototype.split(pointerIdBits);
- event.setDownTime(mPointerTracker.getLastInjectedDownEventTime());
- event.setAction(action);
- sendMotionEvent(event, policyFlags);
- event.recycle();
+ prototype.setAction(action);
+
+ MotionEvent event = null;
+ if (pointerIdBits == ALL_POINTER_ID_BITS) {
+ event = prototype;
+ } else {
+ event = prototype.split(pointerIdBits);
+ }
+ if (action == MotionEvent.ACTION_DOWN) {
+ event.setDownTime(event.getEventTime());
+ } else {
+ event.setDownTime(mPointerTracker.getLastInjectedDownEventTime());
+ }
+
+ if (DEBUG) {
+ Slog.d(LOG_TAG_INJECTED, "Injecting event: " + event + ", policyFlags=0x"
+ + Integer.toHexString(policyFlags));
+ }
+
+ // Make sure that the user will see the event.
+ policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER;
+ mPointerTracker.onInjectedMotionEvent(event);
+ mInputFilter.sendInputEvent(event, policyFlags);
+
+ if (event != prototype) {
+ event.recycle();
+ }
}
/**
@@ -787,19 +746,16 @@ public class TouchExplorer implements Explorer {
final float secondPtrX = event.getX(secondPtrIndex);
final float secondPtrY = event.getY(secondPtrIndex);
- // Check if the pointers are close enough.
- final float deltaX = firstPtrX - secondPtrX;
- final float deltaY = firstPtrY - secondPtrY;
- final float deltaMove = (float) Math.hypot(deltaX, deltaY);
- if (deltaMove > mDraggingDistance) {
- return false;
- }
-
// Check if the pointers are moving in the same direction.
final float firstDeltaX =
firstPtrX - pointerTracker.getReceivedPointerDownX(firstPtrIndex);
final float firstDeltaY =
firstPtrY - pointerTracker.getReceivedPointerDownY(firstPtrIndex);
+
+ if (firstDeltaX == 0 && firstDeltaY == 0) {
+ return true;
+ }
+
final float firstMagnitude =
(float) Math.sqrt(firstDeltaX * firstDeltaX + firstDeltaY * firstDeltaY);
final float firstXNormalized =
@@ -811,6 +767,11 @@ public class TouchExplorer implements Explorer {
secondPtrX - pointerTracker.getReceivedPointerDownX(secondPtrIndex);
final float secondDeltaY =
secondPtrY - pointerTracker.getReceivedPointerDownY(secondPtrIndex);
+
+ if (secondDeltaX == 0 && secondDeltaY == 0) {
+ return true;
+ }
+
final float secondMagnitude =
(float) Math.sqrt(secondDeltaX * secondDeltaX + secondDeltaY * secondDeltaY);
final float secondXNormalized =
@@ -839,23 +800,6 @@ public class TouchExplorer implements Explorer {
}
/**
- * Sends a motion event to the input filter for injection.
- *
- * @param event The event to send.
- * @param policyFlags The policy flags associated with the event.
- */
- private void sendMotionEvent(MotionEvent event, int policyFlags) {
- if (DEBUG) {
- Slog.d(LOG_TAG_INJECTED, "Injecting event: " + event + ", policyFlags=0x"
- + Integer.toHexString(policyFlags));
- }
- // Make sure that the user will see the event.
- policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER;
- mPointerTracker.onInjectedMotionEvent(event);
- mInputFilter.sendInputEvent(event, policyFlags);
- }
-
- /**
* Clears the internal state of this explorer.
*/
public void clear() {
@@ -1013,6 +957,7 @@ public class TouchExplorer implements Explorer {
switch (action) {
case MotionEvent.ACTION_DOWN: {
handleInjectedPointerDown(event.getActionIndex(), event);
+ mLastInjectedDownEventTime = event.getDownTime();
} break;
case MotionEvent.ACTION_POINTER_DOWN: {
handleInjectedPointerDown(event.getActionIndex(), event);
@@ -1270,7 +1215,6 @@ public class TouchExplorer implements Explorer {
final int pointerId = event.getPointerId(pointerIndex);
final int pointerFlag = (1 << pointerId);
mInjectedPointersDown |= pointerFlag;
- mLastInjectedDownEventTime = event.getEventTime();
}
/**
@@ -1406,7 +1350,11 @@ public class TouchExplorer implements Explorer {
public void run() {
mCurrentState = STATE_DELEGATING;
// Make sure the scheduled hover exit is delivered.
- mSendHoverDelayed.forceSendAndRemove();
+ mSendHoverDelayed.remove();
+ final int pointerId = mPointerTracker.getPrimaryActivePointerId();
+ final int pointerIdBits = (1 << pointerId);
+ ensureHoverExitSent(mEvent, pointerIdBits, mPolicyFlags);
+
sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags);
mTouchExploreGestureInProgress = false;
mLastTouchExploreEvent = null;