diff options
11 files changed, 84 insertions, 26 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index a4ac61b1f086..cb60b011d00e 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2724,12 +2724,12 @@ 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 { method public static String actionToString(int); method public final void setDisplayId(int); + field public static final int FLAG_IS_ACCESSIBILITY_EVENT = 2048; // 0x800 field public static final int LAST_KEYCODE = 288; // 0x120 } @@ -2747,6 +2747,7 @@ package android.view { method public void setActionButton(int); method public void setButtonState(int); method public void setDisplayId(int); + field public static final int FLAG_IS_ACCESSIBILITY_EVENT = 2048; // 0x800 } @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public @interface RemotableViewMethod { diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 782a992d28e5..4f1354d7eee6 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -444,13 +444,6 @@ 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/KeyEvent.java b/core/java/android/view/KeyEvent.java index 37f0a64df613..cda9b233576c 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -16,6 +16,7 @@ package android.view; +import static android.os.IInputConstants.INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT; import static android.view.Display.INVALID_DISPLAY; import android.annotation.NonNull; @@ -1222,6 +1223,14 @@ public class KeyEvent extends InputEvent implements Parcelable { public static final int FLAG_FALLBACK = 0x400; /** + * This flag indicates that this event was modified by or generated from an accessibility + * service. Value = 0x800 + * @hide + */ + @TestApi + public static final int FLAG_IS_ACCESSIBILITY_EVENT = INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT; + + /** * Signifies that the key is being predispatched. * @hide */ diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 0483d0ba7615..69ff64f3d6a5 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -16,6 +16,7 @@ package android.view; +import static android.os.IInputConstants.INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT; import static android.view.Display.DEFAULT_DISPLAY; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -494,6 +495,14 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int FLAG_NO_FOCUS_CHANGE = 0x40; /** + * This flag indicates that this event was modified by or generated from an accessibility + * service. Value = 0x800 + * @hide + */ + @TestApi + public static final int FLAG_IS_ACCESSIBILITY_EVENT = INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT; + + /** * Private flag that indicates when the system has detected that this motion event * may be inconsistent with respect to the sequence of previously delivered motion events, * such as when a pointer move event is sent but the pointer is not down. diff --git a/core/java/android/view/VerifiedInputEvent.java b/core/java/android/view/VerifiedInputEvent.java index e2db50165f77..cc6fbe7f5171 100644 --- a/core/java/android/view/VerifiedInputEvent.java +++ b/core/java/android/view/VerifiedInputEvent.java @@ -20,6 +20,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SuppressLint; import android.os.Parcel; import android.os.Parcelable; @@ -157,4 +158,28 @@ public abstract class VerifiedInputEvent implements Parcelable { throw new IllegalArgumentException("Unexpected input event type in parcel."); } }; + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + @SuppressWarnings("unchecked") + VerifiedInputEvent that = (VerifiedInputEvent) o; + return mType == that.mType + && getDeviceId() == that.getDeviceId() + && getEventTimeNanos() == that.getEventTimeNanos() + && getSource() == that.getSource() + && getDisplayId() == that.getDisplayId(); + } + + @Override + public int hashCode() { + int _hash = 1; + _hash = 31 * _hash + mType; + _hash = 31 * _hash + getDeviceId(); + _hash = 31 * _hash + Long.hashCode(getEventTimeNanos()); + _hash = 31 * _hash + getSource(); + _hash = 31 * _hash + getDisplayId(); + return _hash; + } } diff --git a/core/java/android/view/VerifiedKeyEvent.java b/core/java/android/view/VerifiedKeyEvent.java index 77a7d0944521..fc357cc9d278 100644 --- a/core/java/android/view/VerifiedKeyEvent.java +++ b/core/java/android/view/VerifiedKeyEvent.java @@ -17,6 +17,7 @@ package android.view; import static android.view.KeyEvent.FLAG_CANCELED; +import static android.view.KeyEvent.FLAG_IS_ACCESSIBILITY_EVENT; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -72,6 +73,7 @@ public final class VerifiedKeyEvent extends VerifiedInputEvent implements Parcel * * @see KeyEvent#getFlags() * @see KeyEvent#FLAG_CANCELED + * @see KeyEvent#FLAG_IS_ACCESSIBILITY_EVENT * * @hide */ @@ -125,6 +127,7 @@ public final class VerifiedKeyEvent extends VerifiedInputEvent implements Parcel // InputDispatcher only verifies a subset of the KeyEvent flags. // These values must be kept in sync with Input.cpp case FLAG_CANCELED: + case FLAG_IS_ACCESSIBILITY_EVENT: return (mFlags & flag) != 0; } return null; diff --git a/core/java/android/view/VerifiedMotionEvent.java b/core/java/android/view/VerifiedMotionEvent.java index 7d8345928bf0..948575cf3104 100644 --- a/core/java/android/view/VerifiedMotionEvent.java +++ b/core/java/android/view/VerifiedMotionEvent.java @@ -16,6 +16,7 @@ package android.view; +import static android.view.MotionEvent.FLAG_IS_ACCESSIBILITY_EVENT; import static android.view.MotionEvent.FLAG_WINDOW_IS_OBSCURED; import static android.view.MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED; @@ -83,6 +84,9 @@ public final class VerifiedMotionEvent extends VerifiedInputEvent implements Par * Returns the flags for this motion event. * * @see MotionEvent#getFlags() + * @see MotionEvent#FLAG_IS_ACCESSIBILITY_EVENT + * @see MotionEvent#FLAG_WINDOW_IS_OBSCURED + * @see MotionEvent#FLAG_WINDOW_IS_PARTIALLY_OBSCURED * @hide */ private int mFlags; @@ -117,6 +121,7 @@ public final class VerifiedMotionEvent extends VerifiedInputEvent implements Par switch(flag) { // InputDispatcher only verifies a subset of the MotionEvent flags. // These values must be kept in sync with Input.cpp + case FLAG_IS_ACCESSIBILITY_EVENT: case FLAG_WINDOW_IS_OBSCURED: case FLAG_WINDOW_IS_PARTIALLY_OBSCURED: return (mFlags & flag) != 0; diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java index 81c934dffa47..bbef3e6aeefa 100644 --- a/core/java/android/view/WindowManagerPolicyConstants.java +++ b/core/java/android/view/WindowManagerPolicyConstants.java @@ -17,7 +17,6 @@ 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; @@ -35,7 +34,6 @@ public interface WindowManagerPolicyConstants { 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; diff --git a/core/tests/coretests/src/android/view/VerifiedMotionEventTest.kt b/core/tests/coretests/src/android/view/VerifiedMotionEventTest.kt index 2c4851f0ab4e..29ad0aa43672 100644 --- a/core/tests/coretests/src/android/view/VerifiedMotionEventTest.kt +++ b/core/tests/coretests/src/android/view/VerifiedMotionEventTest.kt @@ -18,6 +18,7 @@ package android.view import android.view.InputDevice.SOURCE_TOUCHSCREEN import android.view.MotionEvent.ACTION_MOVE +import android.view.MotionEvent.FLAG_IS_ACCESSIBILITY_EVENT import android.view.MotionEvent.FLAG_WINDOW_IS_OBSCURED import android.view.MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED import android.view.MotionEvent.FLAG_TAINTED @@ -49,6 +50,7 @@ class VerifiedMotionEventTest { assertEquals(RAW_Y, event.rawY, 0f) assertEquals(ACTION_MASKED, event.actionMasked) assertEquals(DOWN_TIME_NANOS, event.downTimeNanos) + assertEquals(FLAGS, event.flags) assertEquals(META_STATE, event.metaState) assertEquals(BUTTON_STATE, event.buttonState) } @@ -128,8 +130,9 @@ class VerifiedMotionEventTest { assertNull(motionEvent.getFlag(0)) // Flag that was not set assertEquals(false, motionEvent.getFlag(FLAG_WINDOW_IS_PARTIALLY_OBSCURED)) - // Flag that was set + // Flags that were set assertEquals(true, motionEvent.getFlag(FLAG_WINDOW_IS_OBSCURED)) + assertEquals(true, motionEvent.getFlag(FLAG_IS_ACCESSIBILITY_EVENT)) // Only 1 flag at a time is accepted assertNull(motionEvent.getFlag( FLAG_WINDOW_IS_PARTIALLY_OBSCURED or FLAG_WINDOW_IS_OBSCURED)) @@ -153,7 +156,7 @@ class VerifiedMotionEventTest { private const val RAW_Y = 200f private const val ACTION_MASKED = ACTION_MOVE private const val DOWN_TIME_NANOS: Long = 1000 - private const val FLAGS = FLAG_WINDOW_IS_OBSCURED + private const val FLAGS = FLAG_WINDOW_IS_OBSCURED or FLAG_IS_ACCESSIBILITY_EVENT private const val META_STATE = 11 private const val BUTTON_STATE = 22 @@ -178,6 +181,7 @@ class VerifiedMotionEventTest { assertEquals(event1.rawY, event2.rawY, 0f) assertEquals(event1.actionMasked, event2.actionMasked) assertEquals(event1.downTimeNanos, event2.downTimeNanos) + assertEquals(event1.flags, event2.flags) assertEquals(event1.metaState, event2.metaState) assertEquals(event1.buttonState, event2.buttonState) } diff --git a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java index ea2c7d2a41e9..2673cd1ac3b8 100644 --- a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java +++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java @@ -30,6 +30,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import android.view.InputDevice; +import android.view.KeyCharacterMap; import android.view.MotionEvent; import android.view.WindowManagerPolicyConstants; @@ -55,7 +56,6 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement */ private static final int EVENT_META_STATE = 0; private static final int EVENT_BUTTON_STATE = 0; - private static final int EVENT_DEVICE_ID = 0; private static final int EVENT_EDGE_FLAGS = 0; private static final int EVENT_SOURCE = InputDevice.SOURCE_TOUCHSCREEN; private static final int EVENT_FLAGS = 0; @@ -122,9 +122,6 @@ 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; @@ -483,8 +480,8 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement } return MotionEvent.obtain(downTime, eventTime, action, touchPointsSize, sPointerProps, sPointerCoords, EVENT_META_STATE, EVENT_BUTTON_STATE, - EVENT_X_PRECISION, EVENT_Y_PRECISION, EVENT_DEVICE_ID, EVENT_EDGE_FLAGS, - EVENT_SOURCE, EVENT_FLAGS); + EVENT_X_PRECISION, EVENT_Y_PRECISION, KeyCharacterMap.VIRTUAL_KEYBOARD, + EVENT_EDGE_FLAGS, EVENT_SOURCE, EVENT_FLAGS); } private static int findPointByStrokeId(TouchPoint[] touchPoints, int touchPointsSize, 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 a71b481372d8..d4908ee78a1d 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java @@ -16,6 +16,7 @@ package com.android.server.accessibility; +import static android.view.KeyCharacterMap.VIRTUAL_KEYBOARD; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_HOVER_MOVE; import static android.view.MotionEvent.ACTION_UP; @@ -112,6 +113,13 @@ public class MotionEventInjectorTest { private static final int CONTINUED_LINE_SEQUENCE_1 = 52; private static final int CONTINUED_LINE_SEQUENCE_2 = 53; + private static final float PRESSURE = 1; + private static final float X_PRECISION = 1; + private static final float Y_PRECISION = 1; + private static final int EDGEFLAGS = 0; + private static final float POINTER_SIZE = 1; + private static final int METASTATE = 0; + MotionEventInjector mMotionEventInjector; IAccessibilityServiceClient mServiceInterface; List<GestureStep> mLineList = new ArrayList<>(); @@ -152,14 +160,18 @@ public class MotionEventInjectorTest { CONTINUED_LINE_STROKE_ID_1, false, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_MID1, CONTINUED_LINE_MID2, CONTINUED_LINE_END); - mClickDownEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, CLICK_POINT.x, CLICK_POINT.y, 0); + mClickDownEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, CLICK_POINT.x, CLICK_POINT.y, + PRESSURE, POINTER_SIZE, METASTATE, X_PRECISION, Y_PRECISION, VIRTUAL_KEYBOARD, + EDGEFLAGS); mClickDownEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN); mClickUpEvent = MotionEvent.obtain(0, CLICK_DURATION, ACTION_UP, CLICK_POINT.x, - CLICK_POINT.y, 0); + CLICK_POINT.y, PRESSURE, POINTER_SIZE, METASTATE, X_PRECISION, Y_PRECISION, + VIRTUAL_KEYBOARD, EDGEFLAGS); mClickUpEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN); mHoverMoveEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, CLICK_POINT.x, CLICK_POINT.y, - 0); + PRESSURE, POINTER_SIZE, METASTATE, X_PRECISION, Y_PRECISION, VIRTUAL_KEYBOARD, + EDGEFLAGS); mHoverMoveEvent.setSource(InputDevice.SOURCE_MOUSE); mIsLineStart = allOf(IS_ACTION_DOWN, isAtPoint(LINE_START), hasStandardInitialization(), @@ -874,12 +886,14 @@ public class MotionEventInjectorTest { return new TypeSafeMatcher<MotionEvent>() { @Override protected boolean matchesSafely(MotionEvent event) { - return (0 == event.getActionIndex()) && (0 == event.getDeviceId()) - && (0 == event.getEdgeFlags()) && (0 == event.getFlags()) - && (0 == event.getMetaState()) && (0F == event.getOrientation()) + return (0 == event.getActionIndex()) && (VIRTUAL_KEYBOARD == event.getDeviceId()) + && (EDGEFLAGS == event.getEdgeFlags()) && (0 == event.getFlags()) + && (METASTATE == event.getMetaState()) && (0F == event.getOrientation()) && (0F == event.getTouchMajor()) && (0F == event.getTouchMinor()) - && (1F == event.getXPrecision()) && (1F == event.getYPrecision()) - && (1 == event.getPointerCount()) && (1F == event.getPressure()) + && (X_PRECISION == event.getXPrecision()) + && (Y_PRECISION == event.getYPrecision()) + && (POINTER_SIZE == event.getSize()) + && (1 == event.getPointerCount()) && (PRESSURE == event.getPressure()) && (InputDevice.SOURCE_TOUCHSCREEN == event.getSource()); } |