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

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

Set FLAG_IS_ACCESSIBILITY_EVENT for events injected from accessibility

If an input event was modified or injected by accessibility, set the
appropriate flag. This helps applications distinguish the real hardware
events from synthesized events.

This also allows a11y services more flexibility in modifying the event
streams coming from real hardware.

Bug: 152399927
Bug: 175069843
Test: atest inputflinger_tests libinput_tests
Change-Id: I805cba4c84582fa4cd4e0892ec00428d4b255ec6
parent 4019c52f
Loading
Loading
Loading
Loading
+23 −7
Original line number Diff line number Diff line
@@ -43,6 +43,13 @@
 * Additional private constants not defined in ndk/ui/input.h.
 */
enum {
#ifdef __linux__
    /* This event was generated or modified by accessibility service. */
    AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT =
            android::os::IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT, // 0x800,
#else
    AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800;
#endif
    /* Signifies that the key is being predispatched */
    AKEY_EVENT_FLAG_PREDISPATCH = 0x20000000,

@@ -81,6 +88,16 @@ enum {
     */
    AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE = 0x40,

#ifdef __linux__
    /**
     * This event was generated or modified by accessibility service.
     */
    AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT =
            android::os::IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT, // 0x800,
#else
    AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800;
#endif

    /* Motion event is inconsistent with previously sent motion events. */
    AMOTION_EVENT_FLAG_TAINTED = 0x80000000,
};
@@ -89,14 +106,15 @@ enum {
 * Allowed VerifiedKeyEvent flags. All other flags from KeyEvent do not get verified.
 * These values must be kept in sync with VerifiedKeyEvent.java
 */
constexpr int32_t VERIFIED_KEY_EVENT_FLAGS = AKEY_EVENT_FLAG_CANCELED;
constexpr int32_t VERIFIED_KEY_EVENT_FLAGS =
        AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;

/**
 * Allowed VerifiedMotionEventFlags. All other flags from MotionEvent do not get verified.
 * These values must be kept in sync with VerifiedMotionEvent.java
 */
constexpr int32_t VERIFIED_MOTION_EVENT_FLAGS =
        AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
constexpr int32_t VERIFIED_MOTION_EVENT_FLAGS = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED |
        AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED | AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;

/**
 * This flag indicates that the point up event has been canceled.
@@ -222,16 +240,14 @@ enum {
    POLICY_FLAG_GESTURE = 0x00000008,

    POLICY_FLAG_RAW_MASK = 0x0000ffff,
#ifdef __linux__
    POLICY_FLAG_INPUTFILTER_TRUSTED = android::os::IInputConstants::POLICY_FLAG_INPUTFILTER_TRUSTED,

#ifdef __linux__
    POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY =
            android::os::IInputConstants::POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
#else
    POLICY_FLAG_INPUTFILTER_TRUSTED = 0x10000,

    POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000,
#endif

    /* These flags are set by the input dispatcher. */

    // Indicates that the input event was injected.
+0 −2
Original line number Diff line number Diff line
@@ -318,8 +318,6 @@ extern std::string getInputDeviceConfigurationFilePathByName(
        const std::string& name, InputDeviceConfigurationFileType type);

enum ReservedInputDeviceId : int32_t {
    // Device id assigned to input events generated inside accessibility service
    ACCESSIBILITY_DEVICE_ID = -2,
    // Device id of a special "virtual" keyboard that is always present.
    VIRTUAL_KEYBOARD_ID = -1,
    // Device id of the "built-in" keyboard if there is one.
+7 −8
Original line number Diff line number Diff line
@@ -42,16 +42,15 @@ interface IInputConstants
    const int INVALID_INPUT_EVENT_ID = 0;

    /**
     * The injected event was originally sent from InputDispatcher. Most likely, the journey of the
     * event looked as follows:
     * InputDispatcherPolicyInterface::filterInputEvent -> InputFilter.java::onInputEvent ->
     * InputFilter.java::sendInputEvent -> InputDispatcher::injectInputEvent, without being modified
     * along the way.
     * The input event was injected from accessibility. Used in policyFlags for input event
     * injection.
     */
    const int POLICY_FLAG_INPUTFILTER_TRUSTED = 0x10000;
    const int POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000;

    /**
     * The input event was injected from accessibility
     * The input event was generated or modified by accessibility service.
     * Shared by both KeyEvent and MotionEvent flags, so this value should not overlap with either
     * set of flags, including in input/Input.h and in android/input.h.
     */
    const int POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000;
    const int INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800;
}
+9 −0
Original line number Diff line number Diff line
@@ -31,6 +31,15 @@
        }
      ]
    },
    {
      "name": "FrameworksCoreTests",
      "options": [
        {
          "include-filter": "android.view.VerifiedKeyEventTest",
          "include-filter": "android.view.VerifiedMotionEventTest"
        }
      ]
    },
    {
      "name": "CtsSecurityTestCases",
      "options": [
+17 −12
Original line number Diff line number Diff line
@@ -3787,7 +3787,7 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
        if (shouldSendKeyToInputFilterLocked(args)) {
            mLock.unlock();

            policyFlags |= POLICY_FLAG_FILTERED | POLICY_FLAG_INPUTFILTER_TRUSTED;
            policyFlags |= POLICY_FLAG_FILTERED;
            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
                return; // event was consumed by the filter
            }
@@ -4010,16 +4010,14 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(
    }

    // For all injected events, set device id = VIRTUAL_KEYBOARD_ID. The only exception is events
    // that have gone through the InputFilter. If the event passed through the InputFilter,
    // but did not get modified, assign the provided device id. If the InputFilter modifies the
    // events in any way, it is responsible for removing this flag.
    // If the injected event originated from accessibility, assign the accessibility device id,
    // so that it can be distinguished from regular injected events.
    // that have gone through the InputFilter. If the event passed through the InputFilter, assign
    // the provided device id. If the InputFilter is accessibility, and it modifies or synthesizes
    // the injected event, it is responsible for setting POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY.
    // For those events, we will set FLAG_IS_ACCESSIBILITY_EVENT to allow apps to distinguish them
    // from events that originate from actual hardware.
    int32_t resolvedDeviceId = VIRTUAL_KEYBOARD_ID;
    if (policyFlags & POLICY_FLAG_INPUTFILTER_TRUSTED) {
    if (policyFlags & POLICY_FLAG_FILTERED) {
        resolvedDeviceId = event->getDeviceId();
    } else if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) {
        resolvedDeviceId = ACCESSIBILITY_DEVICE_ID;
    }

    std::queue<std::unique_ptr<EventEntry>> injectedEntries;
@@ -4032,6 +4030,9 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(
            }

            int32_t flags = incomingKey.getFlags();
            if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) {
                flags |= AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
            }
            int32_t keyCode = incomingKey.getKeyCode();
            int32_t metaState = incomingKey.getMetaState();
            accelerateMetaShortcuts(resolvedDeviceId, action,
@@ -4073,6 +4074,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(
            size_t pointerCount = motionEvent.getPointerCount();
            const PointerProperties* pointerProperties = motionEvent.getPointerProperties();
            int32_t actionButton = motionEvent.getActionButton();
            int32_t flags = motionEvent.getFlags();
            int32_t displayId = motionEvent.getDisplayId();
            if (!validateMotionEvent(action, actionButton, pointerCount, pointerProperties)) {
                return InputEventInjectionResult::FAILED;
@@ -4088,6 +4090,10 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(
                }
            }

            if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) {
                flags |= AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
            }

            mLock.lock();
            const nsecs_t* sampleEventTimes = motionEvent.getSampleEventTimes();
            const PointerCoords* samplePointerCoords = motionEvent.getSamplePointerCoords();
@@ -4095,8 +4101,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(
                    std::make_unique<MotionEntry>(motionEvent.getId(), *sampleEventTimes,
                                                  resolvedDeviceId, motionEvent.getSource(),
                                                  motionEvent.getDisplayId(), policyFlags, action,
                                                  actionButton, motionEvent.getFlags(),
                                                  motionEvent.getMetaState(),
                                                  actionButton, flags, motionEvent.getMetaState(),
                                                  motionEvent.getButtonState(),
                                                  motionEvent.getClassification(),
                                                  motionEvent.getEdgeFlags(),
@@ -4116,7 +4121,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(
                        std::make_unique<MotionEntry>(motionEvent.getId(), *sampleEventTimes,
                                                      resolvedDeviceId, motionEvent.getSource(),
                                                      motionEvent.getDisplayId(), policyFlags,
                                                      action, actionButton, motionEvent.getFlags(),
                                                      action, actionButton, flags,
                                                      motionEvent.getMetaState(),
                                                      motionEvent.getButtonState(),
                                                      motionEvent.getClassification(),
Loading