Skip to content

Commit 47c52a8

Browse files
sganovAndroid (Google) Code Review
authored andcommitted
Merge "Some accessibility events not sent from touch explorer if apps misbehave." into jb-mr1-dev
2 parents 8af2a13 + fe304b8 commit 47c52a8

File tree

5 files changed

+58
-0
lines changed

5 files changed

+58
-0
lines changed
190 Bytes
Loading
172 Bytes
Loading
-741 Bytes
Binary file not shown.
205 Bytes
Loading

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ class TouchExplorer implements EventStreamTransformation {
102102
// The timeout after which we are no longer trying to detect a gesture.
103103
private static final int EXIT_GESTURE_DETECTION_TIMEOUT = 2000;
104104

105+
// The timeout to send interaction end events in case we did not
106+
// receive the expected hover exit event due to a misbehaving app.
107+
private static final int SEND_INTERACTION_END_EVENTS_TIMEOUT = 200;
108+
105109
// Temporary array for storing pointer IDs.
106110
private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT];
107111

@@ -135,6 +139,9 @@ class TouchExplorer implements EventStreamTransformation {
135139
// Command for delayed sending of a hover exit event.
136140
private final SendHoverDelayed mSendHoverExitDelayed;
137141

142+
// Command for delayed sending of interaction ending events.
143+
private final SendInteractionEndEventsDelayed mSendInteractionEndEventsDelayed;
144+
138145
// Command for delayed sending of a long press.
139146
private final PerformLongPressDelayed mPerformLongPressDelayed;
140147

@@ -233,6 +240,7 @@ public TouchExplorer(Context context, AccessibilityManagerService service) {
233240
mGestureLibrary.load();
234241
mSendHoverEnterDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_ENTER, true);
235242
mSendHoverExitDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_EXIT, false);
243+
mSendInteractionEndEventsDelayed = new SendInteractionEndEventsDelayed();
236244
mDoubleTapDetector = new DoubleTapDetector();
237245
final float density = context.getResources().getDisplayMetrics().density;
238246
mScaledMinPointerDistanceToUseMiddleLocation =
@@ -278,6 +286,7 @@ private void clear(MotionEvent event, int policyFlags) {
278286
mSendHoverExitDelayed.remove();
279287
mPerformLongPressDelayed.remove();
280288
mExitGestureDetectionModeDelayed.remove();
289+
mSendInteractionEndEventsDelayed.remove();
281290
// Reset the pointer trackers.
282291
mReceivedPointerTracker.clear();
283292
mInjectedPointerTracker.clear();
@@ -334,6 +343,7 @@ public void onAccessibilityEvent(AccessibilityEvent event) {
334343
// last hover exit event.
335344
if (mTouchExplorationGestureEnded
336345
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
346+
mSendInteractionEndEventsDelayed.remove();
337347
mTouchExplorationGestureEnded = false;
338348
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
339349
}
@@ -342,6 +352,7 @@ public void onAccessibilityEvent(AccessibilityEvent event) {
342352
// last hover exit and the touch exploration gesture end events.
343353
if (mTouchInteractionEnded
344354
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
355+
mSendInteractionEndEventsDelayed.remove();
345356
mTouchInteractionEnded = false;
346357
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
347358
}
@@ -416,6 +427,10 @@ private void handleMotionEventStateTouchExploring(MotionEvent event, int policyF
416427
mSendHoverExitDelayed.remove();
417428
}
418429

430+
if (mSendInteractionEndEventsDelayed.isPending()) {
431+
mSendInteractionEndEventsDelayed.forceSendAndRemove();
432+
}
433+
419434
mPerformLongPressDelayed.remove();
420435

421436
// If we have the first tap schedule a long press and break
@@ -873,6 +888,9 @@ private void sendExitEventsIfNeeded(int policyFlags) {
873888
final int pointerIdBits = event.getPointerIdBits();
874889
mTouchExplorationGestureEnded = true;
875890
mTouchInteractionEnded = true;
891+
if (!mSendInteractionEndEventsDelayed.isPending()) {
892+
mSendInteractionEndEventsDelayed.post();
893+
}
876894
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits, policyFlags);
877895
}
878896
}
@@ -1484,17 +1502,57 @@ public void run() {
14841502
} else {
14851503
mTouchExplorationGestureEnded = true;
14861504
mTouchInteractionEnded = true;
1505+
if (!mSendInteractionEndEventsDelayed.isPending()) {
1506+
mSendInteractionEndEventsDelayed.post();
1507+
}
14871508
}
14881509
} else {
14891510
if (!mGestureStarted) {
14901511
mTouchInteractionEnded = true;
1512+
if (!mSendInteractionEndEventsDelayed.isPending()) {
1513+
mSendInteractionEndEventsDelayed.post();
1514+
}
14911515
}
14921516
}
14931517
sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags);
14941518
clear();
14951519
}
14961520
}
14971521

1522+
private class SendInteractionEndEventsDelayed implements Runnable {
1523+
1524+
public void remove() {
1525+
mHandler.removeCallbacks(this);
1526+
}
1527+
1528+
public void post() {
1529+
mHandler.postDelayed(this, SEND_INTERACTION_END_EVENTS_TIMEOUT);
1530+
}
1531+
1532+
public boolean isPending() {
1533+
return mHandler.hasCallbacks(this);
1534+
}
1535+
1536+
public void forceSendAndRemove() {
1537+
if (isPending()) {
1538+
run();
1539+
remove();
1540+
}
1541+
}
1542+
1543+
@Override
1544+
public void run() {
1545+
if (mTouchExplorationGestureEnded) {
1546+
mTouchExplorationGestureEnded = false;
1547+
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
1548+
}
1549+
if (mTouchInteractionEnded) {
1550+
mTouchInteractionEnded = false;
1551+
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
1552+
}
1553+
}
1554+
}
1555+
14981556
@Override
14991557
public String toString() {
15001558
return LOG_TAG;

0 commit comments

Comments
 (0)