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

Commit 8ab9434e authored by Siarhei Vishniakou's avatar Siarhei Vishniakou Committed by Automerger Merge Worker
Browse files

Merge "Use the injected device id for events that are a11y trusted" into sc-dev am: 9473f556

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/14673429

Change-Id: Ia6e1a3919bdf0b01385dce1d54dc9e95d66a6782
parents 88ee9d03 9473f556
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@
 */
 */


#include <android/input.h>
#include <android/input.h>
#include <android/os/IInputConstants.h>
#include <math.h>
#include <math.h>
#include <stdint.h>
#include <stdint.h>
#include <ui/Transform.h>
#include <ui/Transform.h>
@@ -220,6 +221,11 @@ enum {


    POLICY_FLAG_RAW_MASK = 0x0000ffff,
    POLICY_FLAG_RAW_MASK = 0x0000ffff,


    POLICY_FLAG_INPUTFILTER_TRUSTED = android::os::IInputConstants::POLICY_FLAG_INPUTFILTER_TRUSTED,

    POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY =
            android::os::IInputConstants::POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,

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


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


enum ReservedInputDeviceId : int32_t {
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.
    // Device id of a special "virtual" keyboard that is always present.
    VIRTUAL_KEYBOARD_ID = -1,
    VIRTUAL_KEYBOARD_ID = -1,
    // Device id of the "built-in" keyboard if there is one.
    // Device id of the "built-in" keyboard if there is one.
+14 −0
Original line number Original line Diff line number Diff line
@@ -40,4 +40,18 @@ interface IInputConstants
     * available.
     * available.
     */
     */
    const int INVALID_INPUT_EVENT_ID = 0;
    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.
     */
    const int POLICY_FLAG_INPUTFILTER_TRUSTED = 0x10000;

    /**
     * The input event was injected from accessibility
     */
    const int POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000;
}
}
+58 −46
Original line number Original line Diff line number Diff line
@@ -3792,7 +3792,7 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
        if (shouldSendKeyToInputFilterLocked(args)) {
        if (shouldSendKeyToInputFilterLocked(args)) {
            mLock.unlock();
            mLock.unlock();


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


    // 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.
    int32_t resolvedDeviceId = VIRTUAL_KEYBOARD_ID;
    if (policyFlags & POLICY_FLAG_INPUTFILTER_TRUSTED) {
        resolvedDeviceId = event->getDeviceId();
    } else if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) {
        resolvedDeviceId = ACCESSIBILITY_DEVICE_ID;
    }

    std::queue<std::unique_ptr<EventEntry>> injectedEntries;
    std::queue<std::unique_ptr<EventEntry>> injectedEntries;
    switch (event->getType()) {
    switch (event->getType()) {
        case AINPUT_EVENT_TYPE_KEY: {
        case AINPUT_EVENT_TYPE_KEY: {
@@ -4026,10 +4039,10 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(
            int32_t flags = incomingKey.getFlags();
            int32_t flags = incomingKey.getFlags();
            int32_t keyCode = incomingKey.getKeyCode();
            int32_t keyCode = incomingKey.getKeyCode();
            int32_t metaState = incomingKey.getMetaState();
            int32_t metaState = incomingKey.getMetaState();
            accelerateMetaShortcuts(VIRTUAL_KEYBOARD_ID, action,
            accelerateMetaShortcuts(resolvedDeviceId, action,
                                    /*byref*/ keyCode, /*byref*/ metaState);
                                    /*byref*/ keyCode, /*byref*/ metaState);
            KeyEvent keyEvent;
            KeyEvent keyEvent;
            keyEvent.initialize(incomingKey.getId(), VIRTUAL_KEYBOARD_ID, incomingKey.getSource(),
            keyEvent.initialize(incomingKey.getId(), resolvedDeviceId, incomingKey.getSource(),
                                incomingKey.getDisplayId(), INVALID_HMAC, action, flags, keyCode,
                                incomingKey.getDisplayId(), INVALID_HMAC, action, flags, keyCode,
                                incomingKey.getScanCode(), metaState, incomingKey.getRepeatCount(),
                                incomingKey.getScanCode(), metaState, incomingKey.getRepeatCount(),
                                incomingKey.getDownTime(), incomingKey.getEventTime());
                                incomingKey.getDownTime(), incomingKey.getEventTime());
@@ -4050,7 +4063,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(
            mLock.lock();
            mLock.lock();
            std::unique_ptr<KeyEntry> injectedEntry =
            std::unique_ptr<KeyEntry> injectedEntry =
                    std::make_unique<KeyEntry>(incomingKey.getId(), incomingKey.getEventTime(),
                    std::make_unique<KeyEntry>(incomingKey.getId(), incomingKey.getEventTime(),
                                               VIRTUAL_KEYBOARD_ID, incomingKey.getSource(),
                                               resolvedDeviceId, incomingKey.getSource(),
                                               incomingKey.getDisplayId(), policyFlags, action,
                                               incomingKey.getDisplayId(), policyFlags, action,
                                               flags, keyCode, incomingKey.getScanCode(), metaState,
                                               flags, keyCode, incomingKey.getScanCode(), metaState,
                                               incomingKey.getRepeatCount(),
                                               incomingKey.getRepeatCount(),
@@ -4060,18 +4073,18 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(
        }
        }


        case AINPUT_EVENT_TYPE_MOTION: {
        case AINPUT_EVENT_TYPE_MOTION: {
            const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
            const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
            int32_t action = motionEvent->getAction();
            int32_t action = motionEvent.getAction();
            size_t pointerCount = motionEvent->getPointerCount();
            size_t pointerCount = motionEvent.getPointerCount();
            const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
            const PointerProperties* pointerProperties = motionEvent.getPointerProperties();
            int32_t actionButton = motionEvent->getActionButton();
            int32_t actionButton = motionEvent.getActionButton();
            int32_t displayId = motionEvent->getDisplayId();
            int32_t displayId = motionEvent.getDisplayId();
            if (!validateMotionEvent(action, actionButton, pointerCount, pointerProperties)) {
            if (!validateMotionEvent(action, actionButton, pointerCount, pointerProperties)) {
                return InputEventInjectionResult::FAILED;
                return InputEventInjectionResult::FAILED;
            }
            }


            if (!(policyFlags & POLICY_FLAG_FILTERED)) {
            if (!(policyFlags & POLICY_FLAG_FILTERED)) {
                nsecs_t eventTime = motionEvent->getEventTime();
                nsecs_t eventTime = motionEvent.getEventTime();
                android::base::Timer t;
                android::base::Timer t;
                mPolicy->interceptMotionBeforeQueueing(displayId, eventTime, /*byref*/ policyFlags);
                mPolicy->interceptMotionBeforeQueueing(displayId, eventTime, /*byref*/ policyFlags);
                if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
                if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
@@ -4081,47 +4094,46 @@ InputEventInjectionResult InputDispatcher::injectInputEvent(
            }
            }


            mLock.lock();
            mLock.lock();
            const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
            const nsecs_t* sampleEventTimes = motionEvent.getSampleEventTimes();
            const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
            const PointerCoords* samplePointerCoords = motionEvent.getSamplePointerCoords();
            std::unique_ptr<MotionEntry> injectedEntry =
            std::unique_ptr<MotionEntry> injectedEntry =
                    std::make_unique<MotionEntry>(motionEvent->getId(), *sampleEventTimes,
                    std::make_unique<MotionEntry>(motionEvent.getId(), *sampleEventTimes,
                                                  VIRTUAL_KEYBOARD_ID, motionEvent->getSource(),
                                                  resolvedDeviceId, motionEvent.getSource(),
                                                  motionEvent->getDisplayId(), policyFlags, action,
                                                  motionEvent.getDisplayId(), policyFlags, action,
                                                  actionButton, motionEvent->getFlags(),
                                                  actionButton, motionEvent.getFlags(),
                                                  motionEvent->getMetaState(),
                                                  motionEvent.getMetaState(),
                                                  motionEvent->getButtonState(),
                                                  motionEvent.getButtonState(),
                                                  motionEvent->getClassification(),
                                                  motionEvent.getClassification(),
                                                  motionEvent->getEdgeFlags(),
                                                  motionEvent.getEdgeFlags(),
                                                  motionEvent->getXPrecision(),
                                                  motionEvent.getXPrecision(),
                                                  motionEvent->getYPrecision(),
                                                  motionEvent.getYPrecision(),
                                                  motionEvent->getRawXCursorPosition(),
                                                  motionEvent.getRawXCursorPosition(),
                                                  motionEvent->getRawYCursorPosition(),
                                                  motionEvent.getRawYCursorPosition(),
                                                  motionEvent->getDownTime(),
                                                  motionEvent.getDownTime(), uint32_t(pointerCount),
                                                  uint32_t(pointerCount), pointerProperties,
                                                  pointerProperties, samplePointerCoords,
                                                  samplePointerCoords, motionEvent->getXOffset(),
                                                  motionEvent.getXOffset(),
                                                  motionEvent->getYOffset());
                                                  motionEvent.getYOffset());
            injectedEntries.push(std::move(injectedEntry));
            injectedEntries.push(std::move(injectedEntry));
            for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
            for (size_t i = motionEvent.getHistorySize(); i > 0; i--) {
                sampleEventTimes += 1;
                sampleEventTimes += 1;
                samplePointerCoords += pointerCount;
                samplePointerCoords += pointerCount;
                std::unique_ptr<MotionEntry> nextInjectedEntry =
                std::unique_ptr<MotionEntry> nextInjectedEntry =
                        std::make_unique<MotionEntry>(motionEvent->getId(), *sampleEventTimes,
                        std::make_unique<MotionEntry>(motionEvent.getId(), *sampleEventTimes,
                                                      VIRTUAL_KEYBOARD_ID, motionEvent->getSource(),
                                                      resolvedDeviceId, motionEvent.getSource(),
                                                      motionEvent->getDisplayId(), policyFlags,
                                                      motionEvent.getDisplayId(), policyFlags,
                                                      action, actionButton, motionEvent->getFlags(),
                                                      action, actionButton, motionEvent.getFlags(),
                                                      motionEvent->getMetaState(),
                                                      motionEvent.getMetaState(),
                                                      motionEvent->getButtonState(),
                                                      motionEvent.getButtonState(),
                                                      motionEvent->getClassification(),
                                                      motionEvent.getClassification(),
                                                      motionEvent->getEdgeFlags(),
                                                      motionEvent.getEdgeFlags(),
                                                      motionEvent->getXPrecision(),
                                                      motionEvent.getXPrecision(),
                                                      motionEvent->getYPrecision(),
                                                      motionEvent.getYPrecision(),
                                                      motionEvent->getRawXCursorPosition(),
                                                      motionEvent.getRawXCursorPosition(),
                                                      motionEvent->getRawYCursorPosition(),
                                                      motionEvent.getRawYCursorPosition(),
                                                      motionEvent->getDownTime(),
                                                      motionEvent.getDownTime(),
                                                      uint32_t(pointerCount), pointerProperties,
                                                      uint32_t(pointerCount), pointerProperties,
                                                      samplePointerCoords,
                                                      samplePointerCoords, motionEvent.getXOffset(),
                                                      motionEvent->getXOffset(),
                                                      motionEvent.getYOffset());
                                                      motionEvent->getYOffset());
                injectedEntries.push(std::move(nextInjectedEntry));
                injectedEntries.push(std::move(nextInjectedEntry));
            }
            }
            break;
            break;
+81 −5
Original line number Original line Diff line number Diff line
@@ -473,6 +473,7 @@ protected:
                          const sp<InputWindowHandle>& focusedWindow = nullptr) {
                          const sp<InputWindowHandle>& focusedWindow = nullptr) {
        FocusRequest request;
        FocusRequest request;
        request.token = window->getToken();
        request.token = window->getToken();
        request.windowName = window->getName();
        if (focusedWindow) {
        if (focusedWindow) {
            request.focusedToken = focusedWindow->getToken();
            request.focusedToken = focusedWindow->getToken();
        }
        }
@@ -1085,6 +1086,20 @@ public:
        return mInputReceiver->consume();
        return mInputReceiver->consume();
    }
    }


    MotionEvent* consumeMotion() {
        InputEvent* event = consume();
        if (event == nullptr) {
            ADD_FAILURE() << "Consume failed : no event";
            return nullptr;
        }
        if (event->getType() != AINPUT_EVENT_TYPE_MOTION) {
            ADD_FAILURE() << "Instead of motion event, got "
                          << inputEventTypeToString(event->getType());
            return nullptr;
        }
        return static_cast<MotionEvent*>(event);
    }

    void assertNoEvents() {
    void assertNoEvents() {
        if (mInputReceiver == nullptr &&
        if (mInputReceiver == nullptr &&
            mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
            mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) {
@@ -2446,13 +2461,10 @@ TEST_F(InputDispatcherTest, NonPointerMotionEvent_NotTransformed) {
                generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, source, ADISPLAY_ID_DEFAULT);
                generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, source, ADISPLAY_ID_DEFAULT);
        mDispatcher->notifyMotion(&motionArgs);
        mDispatcher->notifyMotion(&motionArgs);


        InputEvent* event = window->consume();
        MotionEvent* event = window->consumeMotion();
        ASSERT_NE(event, nullptr);
        ASSERT_NE(event, nullptr);
        ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType())
                << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION)
                << " event, got " << inputEventTypeToString(event->getType()) << " event";


        const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
        const MotionEvent& motionEvent = *event;
        EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, motionEvent.getAction());
        EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, motionEvent.getAction());
        EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());
        EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount());


@@ -3128,6 +3140,70 @@ TEST_F(InputFilterTest, KeyEvent_InputFilter) {
    testNotifyKey(/*expectToBeFiltered*/ false);
    testNotifyKey(/*expectToBeFiltered*/ false);
}
}


class InputFilterInjectionPolicyTest : public InputDispatcherTest {
protected:
    virtual void SetUp() override {
        InputDispatcherTest::SetUp();

        /**
         * We don't need to enable input filter to test the injected event policy, but we enabled it
         * here to make the tests more realistic, since this policy only matters when inputfilter is
         * on.
         */
        mDispatcher->setInputFilterEnabled(true);

        std::shared_ptr<InputApplicationHandle> application =
                std::make_shared<FakeApplicationHandle>();
        mWindow =
                new FakeWindowHandle(application, mDispatcher, "Test Window", ADISPLAY_ID_DEFAULT);

        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
        mWindow->setFocusable(true);
        mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
        setFocusedWindow(mWindow);
        mWindow->consumeFocusEvent(true);
    }

    void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId) {
        KeyEvent event;

        const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
        event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
                         ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A,
                         KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime);
        const int32_t additionalPolicyFlags =
                POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
        ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
                  mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
                                                InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
                                                policyFlags | additionalPolicyFlags));

        InputEvent* received = mWindow->consume();
        ASSERT_NE(nullptr, received);
        ASSERT_EQ(resolvedDeviceId, received->getDeviceId());
    }

private:
    sp<FakeWindowHandle> mWindow;
};

TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
    // We don't need POLICY_FLAG_FILTERED here, but it will be set in practice, so keep it to make
    // the test more closely resemble the real usage
    testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INPUTFILTER_TRUSTED, 3 /*injectedDeviceId*/,
                    3 /*resolvedDeviceId*/);
}

TEST_F(InputFilterInjectionPolicyTest, EventsInjectedFromAccessibility_HaveAccessibilityDeviceId) {
    testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
                    3 /*injectedDeviceId*/, ACCESSIBILITY_DEVICE_ID /*resolvedDeviceId*/);
}

TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
    testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/,
                    VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/);
}

class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
    virtual void SetUp() override {
    virtual void SetUp() override {
        InputDispatcherTest::SetUp();
        InputDispatcherTest::SetUp();