Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12144442 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

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
parent 6b5bbd62
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 {
+7 −0
Original line number Diff line number Diff line
@@ -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) {
+7 −1
Original line number Diff line number Diff line
@@ -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;
+12 −3
Original line number Diff line number Diff line
@@ -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);
        }
    }
+14 −9
Original line number Diff line number Diff line
@@ -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