diff options
| author | 2025-02-06 13:20:52 -0800 | |
|---|---|---|
| committer | 2025-02-06 13:20:52 -0800 | |
| commit | 0c25ba71ed2270681ae337a4aca151f1c3aaa0ad (patch) | |
| tree | 53638078b40197962e673d2c7afbfb09a94bf9c8 /services/accessibility/java | |
| parent | c6c026a76968afdcd3fb5822f8e8384028cd9be9 (diff) | |
| parent | 614c6be5aea885432f86b9638de15c1f292f6402 (diff) | |
Merge changes from topic "b384451671" into main
* changes:
Removes ACTION_CANCEL which caused InputDispatcher inconsistency.
Cleanup mOpenGesturesInProgress to use a simple boolean.
Diffstat (limited to 'services/accessibility/java')
| -rw-r--r-- | services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java | 69 |
1 files changed, 41 insertions, 28 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java index b2169535d0de..a7203b0b83f1 100644 --- a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java +++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java @@ -28,7 +28,6 @@ import android.os.RemoteException; import android.os.SystemClock; import android.util.IntArray; import android.util.Slog; -import android.util.SparseArray; import android.util.SparseIntArray; import android.view.InputDevice; import android.view.KeyCharacterMap; @@ -67,7 +66,7 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement private static MotionEvent.PointerProperties[] sPointerProps; private final Handler mHandler; - private final SparseArray<Boolean> mOpenGesturesInProgress = new SparseArray<>(); + private boolean mOpenTouchGestureInProgress = false; private final AccessibilityTraceManager mTrace; private IAccessibilityServiceClient mServiceInterfaceForCurrentGesture; @@ -116,6 +115,8 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_INJECT_EVENTS, args)); } + // Note: MotionEventInjector is the first transformation in the AccessibilityInputFilter stream + // so any event that arrives here is a real event from a real user interaction. @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { if (mTrace.isA11yTracingEnabledForTypes( @@ -124,22 +125,30 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement AccessibilityTrace.FLAGS_INPUT_FILTER | AccessibilityTrace.FLAGS_GESTURE, "event=" + event + ";rawEvent=" + rawEvent + ";policyFlags=" + policyFlags); } - // MotionEventInjector would cancel any injected gesture when any MotionEvent arrives. - // For user using an external device to control the pointer movement, it's almost - // impossible to perform the gestures. Any slightly unintended movement results in the - // cancellation of the gesture. + // InputDispatcher cancels an injected touch gesture if another MotionEvent arrives on this + // display from another device or source, like a real touch or a real mouse pointer. + // For user using an external device to control the pointer movement, it becomes difficult + // to perform injected gestures because slight unintended movement results in cancellation + // of the injected gesture; to fix this we swallow real mouse MotionEvents while an injected + // touch gesture is in progress, preventing the mouse events from reaching InputDispatcher. if ((event.isFromSource(InputDevice.SOURCE_MOUSE) && event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) - && mOpenGesturesInProgress.get(EVENT_SOURCE, false)) { + && mOpenTouchGestureInProgress) { return; } - cancelAnyPendingInjectedEvents(); - if (!android.view.accessibility.Flags.preventA11yNontoolFromInjectingIntoSensitiveViews()) { - // Indicate that the input event is injected from accessibility, to let applications - // distinguish it from events injected by other means. - policyFlags |= WindowManagerPolicyConstants.FLAG_INJECTED_FROM_ACCESSIBILITY; + if (Flags.motionEventInjectorCancelFix()) { + // Pass this real event down the stream unmodified. + super.onMotionEvent(event, rawEvent, policyFlags); + } else { + cancelAnyPendingInjectedEvents(); + if (!android.view.accessibility.Flags + .preventA11yNontoolFromInjectingIntoSensitiveViews()) { + // Indicate that the input event is injected from accessibility, to let applications + // distinguish it from events injected by other means. + policyFlags |= WindowManagerPolicyConstants.FLAG_INJECTED_FROM_ACCESSIBILITY; + } + sendMotionEventToNext(event, rawEvent, policyFlags); } - sendMotionEventToNext(event, rawEvent, policyFlags); } @Override @@ -148,8 +157,8 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement * Reset state for motion events passing through so we won't send a cancel event for * them. */ - if (!mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) { - mOpenGesturesInProgress.put(inputSource, false); + if (!mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT) && inputSource == EVENT_SOURCE) { + mOpenTouchGestureInProgress = false; } } @@ -224,8 +233,10 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement } if (!continuingGesture) { cancelAnyPendingInjectedEvents(); - // Injected gestures have been canceled, but real gestures still need cancelling - cancelAnyGestureInProgress(EVENT_SOURCE); + if (!Flags.motionEventInjectorCancelFix()) { + // Injected gestures have been canceled, but real gestures still need cancelling + cancelInjectedGestureInProgress(); + } } mServiceInterfaceForCurrentGesture = serviceInterface; @@ -323,18 +334,20 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement int policyFlags) { if (getNext() != null) { super.onMotionEvent(event, rawEvent, policyFlags); - if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { - mOpenGesturesInProgress.put(event.getSource(), true); - } - if ((event.getActionMasked() == MotionEvent.ACTION_UP) - || (event.getActionMasked() == MotionEvent.ACTION_CANCEL)) { - mOpenGesturesInProgress.put(event.getSource(), false); + if (event.getSource() == EVENT_SOURCE) { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + mOpenTouchGestureInProgress = true; + } + if ((event.getActionMasked() == MotionEvent.ACTION_UP) + || (event.getActionMasked() == MotionEvent.ACTION_CANCEL)) { + mOpenTouchGestureInProgress = false; + } } } } - private void cancelAnyGestureInProgress(int source) { - if ((getNext() != null) && mOpenGesturesInProgress.get(source, false)) { + private void cancelInjectedGestureInProgress() { + if ((getNext() != null) && mOpenTouchGestureInProgress) { long now = SystemClock.uptimeMillis(); MotionEvent cancelEvent = obtainMotionEvent(now, now, MotionEvent.ACTION_CANCEL, getLastTouchPoints(), 1); @@ -348,14 +361,14 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement policyFlags |= WindowManagerPolicyConstants.FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL; } sendMotionEventToNext(cancelEvent, cancelEvent, policyFlags); - mOpenGesturesInProgress.put(source, false); + mOpenTouchGestureInProgress = false; } } private void cancelAnyPendingInjectedEvents() { if (mHandler.hasMessages(MESSAGE_SEND_MOTION_EVENT)) { mHandler.removeMessages(MESSAGE_SEND_MOTION_EVENT); - cancelAnyGestureInProgress(EVENT_SOURCE); + cancelInjectedGestureInProgress(); for (int i = mSequencesInProgress.size() - 1; i >= 0; i--) { notifyService(mServiceInterfaceForCurrentGesture, mSequencesInProgress.get(i), false); @@ -363,7 +376,7 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement } } else if (mNumLastTouchPoints != 0) { // An injected gesture is in progress and waiting for a continuation. Cancel it. - cancelAnyGestureInProgress(EVENT_SOURCE); + cancelInjectedGestureInProgress(); } mNumLastTouchPoints = 0; mStrokeIdToPointerId.clear(); |