diff options
| author | 2021-05-21 05:28:09 +0000 | |
|---|---|---|
| committer | 2021-06-04 21:15:43 +0000 | |
| commit | 12144442602f8facfa90dc91e52fbde0a6d23b88 (patch) | |
| tree | 5f4959a5076244db20fa543b4efc46f33fe142f1 | |
| parent | 6b5bbd62f98165940d348c0a707f2bced4203a15 (diff) | |
Remove FLAG_INPUTFILTER_TRUSTED in MotionEventInjector
All input events coming into inputfilter from
InputDispatcher will now have FLAG_INPUTFILTER_TRUSTED set by default.
It is now up to the inputfilter (a11y) to remove this flag when appropriate.
One such case is where an unknown a11y service is injecting the events.
From auditing the a11y code, the only such place is MotionEventInjector.
Therefore, label all events coming out of MotionEventInjector as
"untrusted" by removing this new flag INPUTFILTER_TRUSTED.
Separately, a11y should be distinguishable from regularly injected input
events. To tell apart the events injected by a11y, add a new flag,
FLAG_INJECTED_FROM_ACCESSIBILITY. This flag requests InputDispatcher to
apply the device id = -2 for the injected events.
Test: atest CtsInputTestCases:android.input.cts.GamepadWithAccessibilityTest
Test: atest MotionEventInjectorTest
Bug: 175069843
Change-Id: I12d4a7bd6fbab8af202f5ae88b6be97ff9e1754c
5 files changed, 41 insertions, 13 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 620323976067..c8538ad3ae80 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2719,6 +2719,7 @@ package android.view { public final class InputDevice implements android.os.Parcelable { method @RequiresPermission("android.permission.DISABLE_INPUT_DEVICE") public void disable(); method @RequiresPermission("android.permission.DISABLE_INPUT_DEVICE") public void enable(); + field public static final int ACCESSIBILITY_DEVICE_ID = -2; // 0xfffffffe } public class KeyEvent extends android.view.InputEvent implements android.os.Parcelable { diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 4f1354d7eee6..782a992d28e5 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -444,6 +444,13 @@ public final class InputDevice implements Parcelable { private static final int VIBRATOR_ID_ALL = -1; + /** + * The device id of input events generated inside accessibility service. + * @hide + */ + @TestApi + public static final int ACCESSIBILITY_DEVICE_ID = -2; + public static final @android.annotation.NonNull Parcelable.Creator<InputDevice> CREATOR = new Parcelable.Creator<InputDevice>() { public InputDevice createFromParcel(Parcel in) { diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java index 7668d80d3cb1..81c934dffa47 100644 --- a/core/java/android/view/WindowManagerPolicyConstants.java +++ b/core/java/android/view/WindowManagerPolicyConstants.java @@ -16,6 +16,9 @@ package android.view; +import static android.os.IInputConstants.POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY; +import static android.os.IInputConstants.POLICY_FLAG_INPUTFILTER_TRUSTED; + import android.annotation.IntDef; import android.os.PowerManager; @@ -27,10 +30,13 @@ import java.lang.annotation.RetentionPolicy; * @hide */ public interface WindowManagerPolicyConstants { - // Policy flags. These flags are also defined in frameworks/base/include/ui/Input.h. + // Policy flags. These flags are also defined in frameworks/base/include/ui/Input.h and + // frameworks/native/libs/input/android/os/IInputConstants.aidl int FLAG_WAKE = 0x00000001; int FLAG_VIRTUAL = 0x00000002; + int FLAG_INPUTFILTER_TRUSTED = POLICY_FLAG_INPUTFILTER_TRUSTED; + int FLAG_INJECTED_FROM_ACCESSIBILITY = POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY; int FLAG_INJECTED = 0x01000000; int FLAG_TRUSTED = 0x02000000; int FLAG_FILTERED = 0x04000000; diff --git a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java index 3310cb4e3e79..ea2c7d2a41e9 100644 --- a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java +++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java @@ -31,9 +31,9 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.view.InputDevice; import android.view.MotionEvent; +import android.view.WindowManagerPolicyConstants; import com.android.internal.os.SomeArgs; -import com.android.server.policy.WindowManagerPolicy; import java.util.ArrayList; import java.util.Arrays; @@ -122,6 +122,12 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement return; } cancelAnyPendingInjectedEvents(); + // The events injected from outside of system_server are not trusted. Remove the flag to + // prevent accessibility service from impersonating a real input device. + policyFlags &= ~WindowManagerPolicyConstants.FLAG_INPUTFILTER_TRUSTED; + // 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); } @@ -156,7 +162,9 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement return false; } MotionEvent motionEvent = (MotionEvent) message.obj; - sendMotionEventToNext(motionEvent, motionEvent, WindowManagerPolicy.FLAG_PASS_TO_USER); + sendMotionEventToNext(motionEvent, motionEvent, + WindowManagerPolicyConstants.FLAG_PASS_TO_USER + | WindowManagerPolicyConstants.FLAG_INJECTED_FROM_ACCESSIBILITY); boolean isEndOfSequence = message.arg1 != 0; if (isEndOfSequence) { notifyService(mServiceInterfaceForCurrentGesture, mSequencesInProgress.get(0), true); @@ -308,7 +316,8 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement MotionEvent cancelEvent = obtainMotionEvent(now, now, MotionEvent.ACTION_CANCEL, getLastTouchPoints(), 1); sendMotionEventToNext(cancelEvent, cancelEvent, - WindowManagerPolicy.FLAG_PASS_TO_USER); + WindowManagerPolicyConstants.FLAG_PASS_TO_USER + | WindowManagerPolicyConstants.FLAG_INJECTED_FROM_ACCESSIBILITY); mOpenGesturesInProgress.put(source, false); } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java index 1ac4a8ed96d0..a71b481372d8 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java @@ -19,6 +19,7 @@ package com.android.server.accessibility; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_HOVER_MOVE; import static android.view.MotionEvent.ACTION_UP; +import static android.view.WindowManagerPolicyConstants.FLAG_INJECTED_FROM_ACCESSIBILITY; import static android.view.WindowManagerPolicyConstants.FLAG_PASS_TO_USER; import static org.hamcrest.CoreMatchers.allOf; @@ -186,9 +187,9 @@ public class MotionEventInjectorTest { verifyNoMoreInteractions(next); mMessageCapturingHandler.sendOneMessage(); // Send a motion event - verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(FLAG_PASS_TO_USER)); - verify(next).onMotionEvent(argThat(mIsLineStart), argThat(mIsLineStart), - eq(FLAG_PASS_TO_USER)); + final int expectedFlags = FLAG_PASS_TO_USER | FLAG_INJECTED_FROM_ACCESSIBILITY; + verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(expectedFlags)); + verify(next).onMotionEvent(argThat(mIsLineStart), argThat(mIsLineStart), eq(expectedFlags)); verifyNoMoreInteractions(next); reset(next); @@ -196,7 +197,7 @@ public class MotionEventInjectorTest { mMessageCapturingHandler.sendOneMessage(); // Send a motion event verify(next).onMotionEvent(argThat(allOf(mIsLineMiddle, hasRightDownTime)), - argThat(allOf(mIsLineMiddle, hasRightDownTime)), eq(FLAG_PASS_TO_USER)); + argThat(allOf(mIsLineMiddle, hasRightDownTime)), eq(expectedFlags)); verifyNoMoreInteractions(next); reset(next); @@ -204,7 +205,7 @@ public class MotionEventInjectorTest { mMessageCapturingHandler.sendOneMessage(); // Send a motion event verify(next).onMotionEvent(argThat(allOf(mIsLineEnd, hasRightDownTime)), - argThat(allOf(mIsLineEnd, hasRightDownTime)), eq(FLAG_PASS_TO_USER)); + argThat(allOf(mIsLineEnd, hasRightDownTime)), eq(expectedFlags)); verifyNoMoreInteractions(next); verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true); @@ -242,7 +243,8 @@ public class MotionEventInjectorTest { mMessageCapturingHandler.sendAllMessages(); // Send all motion events reset(next); mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0); - verify(next).onMotionEvent(argThat(mIsClickDown), argThat(mIsClickDown), eq(0)); + verify(next).onMotionEvent(argThat(mIsClickDown), argThat(mIsClickDown), + eq(FLAG_INJECTED_FROM_ACCESSIBILITY)); } @Test @@ -258,7 +260,8 @@ public class MotionEventInjectorTest { mMessageCapturingHandler.sendOneMessage(); // Send a motion event verify(next).onMotionEvent( - argThat(mIsLineStart), argThat(mIsLineStart), eq(FLAG_PASS_TO_USER)); + argThat(mIsLineStart), argThat(mIsLineStart), + eq(FLAG_PASS_TO_USER | FLAG_INJECTED_FROM_ACCESSIBILITY)); } @Test @@ -289,9 +292,11 @@ public class MotionEventInjectorTest { reset(next); mMessageCapturingHandler.sendOneMessage(); // Send a motion event - verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(FLAG_PASS_TO_USER)); + verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), + eq(FLAG_PASS_TO_USER | FLAG_INJECTED_FROM_ACCESSIBILITY)); verify(next).onMotionEvent( - argThat(mIsLineStart), argThat(mIsLineStart), eq(FLAG_PASS_TO_USER)); + argThat(mIsLineStart), argThat(mIsLineStart), + eq(FLAG_PASS_TO_USER | FLAG_INJECTED_FROM_ACCESSIBILITY)); } @Test |