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
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user