diff options
4 files changed, 89 insertions, 9 deletions
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig index 7f0bf0375b4a..722255404dd1 100644 --- a/services/accessibility/accessibility.aconfig +++ b/services/accessibility/accessibility.aconfig @@ -145,6 +145,16 @@ flag { } flag { + name: "event_dispatcher_raw_event" + namespace: "accessibility" + description: "Fixes EventDispatcher#sendMotionEvent callers to properly provide raw event" + bug: "385812366" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "fix_drag_pointer_when_ending_drag" namespace: "accessibility" description: "Send the correct pointer id when transitioning from dragging to delegating states." diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java b/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java index bf9202f1b266..5c0bbf4e01eb 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/EventDispatcher.java @@ -31,6 +31,7 @@ import android.view.accessibility.AccessibilityManager; import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.accessibility.EventStreamTransformation; +import com.android.server.accessibility.Flags; import com.android.server.policy.WindowManagerPolicy; /** @@ -297,7 +298,8 @@ class EventDispatcher { sendMotionEvent( prototype, action, - mState.getLastReceivedEvent(), + Flags.eventDispatcherRawEvent() ? mState.getLastReceivedRawEvent() : + mState.getLastReceivedEvent(), pointerIdBits, policyFlags); } @@ -327,7 +329,8 @@ class EventDispatcher { sendMotionEvent( event, action, - mState.getLastReceivedEvent(), + Flags.eventDispatcherRawEvent() ? mState.getLastReceivedRawEvent() : + mState.getLastReceivedEvent(), pointerIdBits, policyFlags); } @@ -394,8 +397,10 @@ class EventDispatcher { continue; } final int action = computeInjectionAction(MotionEvent.ACTION_POINTER_UP, i); - sendMotionEvent( - prototype, action, mState.getLastReceivedEvent(), pointerIdBits, policyFlags); + sendMotionEvent(prototype, action, + Flags.eventDispatcherRawEvent() ? mState.getLastReceivedRawEvent() : + mState.getLastReceivedEvent(), + pointerIdBits, policyFlags); pointerIdBits &= ~(1 << pointerId); } } diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java index 0cbbf6da022b..59e55e5f4b1e 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java @@ -506,13 +506,14 @@ public class TouchExplorer extends BaseEventStreamTransformation // We have just decided that the user is touch, // exploring so start sending events. - mSendHoverEnterAndMoveDelayed.addEvent(event, mState.getLastReceivedEvent()); + mSendHoverEnterAndMoveDelayed.addEvent(event, + Flags.eventDispatcherRawEvent() ? rawEvent : mState.getLastReceivedEvent()); mSendHoverEnterAndMoveDelayed.forceSendAndRemove(); mSendHoverExitDelayed.cancel(); mDispatcher.sendMotionEvent( event, ACTION_HOVER_MOVE, - event, + Flags.eventDispatcherRawEvent() ? rawEvent : event, pointerIdBits, policyFlags); return true; @@ -1108,7 +1109,8 @@ public class TouchExplorer extends BaseEventStreamTransformation * * @param policyFlags The policy flags associated with the event. */ - private void sendHoverExitAndTouchExplorationGestureEndIfNeeded(int policyFlags) { + @VisibleForTesting + void sendHoverExitAndTouchExplorationGestureEndIfNeeded(int policyFlags) { MotionEvent event = mState.getLastInjectedHoverEvent(); if (event != null && event.getActionMasked() != ACTION_HOVER_EXIT) { final int pointerIdBits = event.getPointerIdBits(); @@ -1118,7 +1120,8 @@ public class TouchExplorer extends BaseEventStreamTransformation mDispatcher.sendMotionEvent( event, ACTION_HOVER_EXIT, - mState.getLastReceivedEvent(), + Flags.eventDispatcherRawEvent() ? mState.getLastReceivedRawEvent() : + mState.getLastReceivedEvent(), pointerIdBits, policyFlags); } @@ -1140,7 +1143,8 @@ public class TouchExplorer extends BaseEventStreamTransformation mDispatcher.sendMotionEvent( event, ACTION_HOVER_ENTER, - mState.getLastReceivedEvent(), + Flags.eventDispatcherRawEvent() ? mState.getLastReceivedRawEvent() : + mState.getLastReceivedEvent(), pointerIdBits, policyFlags); } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java index e5005d1beed4..1af59daa9c78 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java @@ -33,6 +33,8 @@ import static com.android.server.accessibility.gestures.TouchState.STATE_DRAGGIN import static com.android.server.accessibility.gestures.TouchState.STATE_GESTURE_DETECTING; import static com.android.server.accessibility.gestures.TouchState.STATE_TOUCH_EXPLORING; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; @@ -132,10 +134,12 @@ public class TouchExplorerTest { */ private class EventCaptor implements EventStreamTransformation { List<MotionEvent> mEvents = new ArrayList<>(); + List<MotionEvent> mRawEvents = new ArrayList<>(); @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { mEvents.add(0, event.copy()); + mRawEvents.add(0, rawEvent.copy()); } @Override @@ -461,6 +465,45 @@ public class TouchExplorerTest { AccessibilityService.GESTURE_3_FINGER_SWIPE_DOWN); } + @Test + public void testSendHoverExitIfNeeded_lastSentHoverExit_noActionNeeded() { + // Prep TouchState so that the last injected hover event was a HOVER_EXIT + mTouchExplorer.getState().onInjectedMotionEvent(hoverExitEvent()); + + mTouchExplorer.sendHoverExitAndTouchExplorationGestureEndIfNeeded(/*policyFlags=*/0); + + assertNoCapturedEvents(); + } + + @Test + @EnableFlags(Flags.FLAG_EVENT_DISPATCHER_RAW_EVENT) + public void testSendHoverExitIfNeeded_lastSentHoverEnter_sendsHoverExit_withCorrectRawEvent() { + final MotionEvent rawEvent = downEvent(); + final MotionEvent modifiedEvent = hoverEnterEvent(); + // Use different display IDs just so that we can differentiate between the raw event and + // the modified event later during test assertions. + final int rawDisplayId = 123; + final int modifiedDisplayId = 456; + rawEvent.setDisplayId(rawDisplayId); + modifiedEvent.setDisplayId(modifiedDisplayId); + // Prep TouchState to track the last received modified and raw events + mTouchExplorer.getState().onReceivedMotionEvent(modifiedEvent, rawEvent, /*policyFlags=*/0); + // Prep TouchState so that the last injected hover event was not a HOVER_EXIT + mTouchExplorer.getState().onInjectedMotionEvent(modifiedEvent); + + mTouchExplorer.sendHoverExitAndTouchExplorationGestureEndIfNeeded(/*policyFlags=*/0); + + assertThat(getCapturedEvents().size()).isEqualTo(1); + assertThat(getCapturedRawEvents().size()).isEqualTo(1); + MotionEvent sentEvent = getCapturedEvents().get(0); + MotionEvent sentRawEvent = getCapturedRawEvents().get(0); + // TouchExplorer should send ACTION_HOVER_EXIT built from the last injected hover event + assertThat(sentEvent.getAction()).isEqualTo(ACTION_HOVER_EXIT); + assertThat(sentEvent.getDisplayId()).isEqualTo(modifiedDisplayId); + // ... while passing along the original raw (unmodified) event + assertThat(sentRawEvent.getDisplayId()).isEqualTo(rawDisplayId); + } + /** * Used to play back event data of a gesture by parsing the log into MotionEvents and sending * them to TouchExplorer. @@ -630,6 +673,10 @@ public class TouchExplorerTest { return ((EventCaptor) mCaptor).mEvents; } + private List<MotionEvent> getCapturedRawEvents() { + return ((EventCaptor) mCaptor).mRawEvents; + } + private MotionEvent cancelEvent() { mLastDownTime = SystemClock.uptimeMillis(); return fromTouchscreen( @@ -688,6 +735,20 @@ public class TouchExplorerTest { return event; } + private MotionEvent hoverEnterEvent() { + mLastDownTime = SystemClock.uptimeMillis(); + return fromTouchscreen( + MotionEvent.obtain( + mLastDownTime, mLastDownTime, ACTION_HOVER_ENTER, DEFAULT_X, DEFAULT_Y, 0)); + } + + private MotionEvent hoverExitEvent() { + mLastDownTime = SystemClock.uptimeMillis(); + return fromTouchscreen( + MotionEvent.obtain( + mLastDownTime, mLastDownTime, ACTION_HOVER_EXIT, DEFAULT_X, DEFAULT_Y, 0)); + } + private void moveEachPointers(MotionEvent event, PointF... points) { final float[] x = new float[points.length]; final float[] y = new float[points.length]; |