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:
Siarhei Vishniakou
2021-05-21 05:28:09 +00:00
parent 6b5bbd62f9
commit 1214444260
5 changed files with 41 additions and 13 deletions

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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