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

Commit e20c9e02 authored by Jeff Brown's avatar Jeff Brown
Browse files

Fix an event injection bug when the policy is bypassed.

Added the concept of a "trusted" event to distinguish between events from
attached input devices or trusted injectors vs. other applications.
This change enables us to move certain policy decisions out of the
dispatcher and into the policy itself where they can be handled more
systematically.

Cherry pick of b931a1b4 from gingerbread into master.

Change-Id: I700a5f07b8b227878cea9437a289a45a245c0424
parent 182e5cf1
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -77,6 +77,7 @@ public interface WindowManagerPolicy {
    public final static int FLAG_VIRTUAL = 0x00000100;
    public final static int FLAG_VIRTUAL = 0x00000100;


    public final static int FLAG_INJECTED = 0x01000000;
    public final static int FLAG_INJECTED = 0x01000000;
    public final static int FLAG_TRUSTED = 0x02000000;


    public final static int FLAG_WOKE_HERE = 0x10000000;
    public final static int FLAG_WOKE_HERE = 0x10000000;
    public final static int FLAG_BRIGHT_HERE = 0x20000000;
    public final static int FLAG_BRIGHT_HERE = 0x20000000;
+4 −0
Original line number Original line Diff line number Diff line
@@ -95,6 +95,10 @@ enum {
    // Indicates that the input event was injected.
    // Indicates that the input event was injected.
    POLICY_FLAG_INJECTED = 0x01000000,
    POLICY_FLAG_INJECTED = 0x01000000,


    // Indicates that the input event is from a trusted source such as a directly attached
    // input device or an application with system-wide event injection permission.
    POLICY_FLAG_TRUSTED = 0x02000000,

    /* These flags are set by the input reader policy as it intercepts each event. */
    /* These flags are set by the input reader policy as it intercepts each event. */


    // Indicates that the screen was off when the event was received and the event
    // Indicates that the screen was off when the event was received and the event
+2 −3
Original line number Original line Diff line number Diff line
@@ -924,7 +924,6 @@ private:
    void drainInboundQueueLocked();
    void drainInboundQueueLocked();
    void releasePendingEventLocked();
    void releasePendingEventLocked();
    void releaseInboundEventLocked(EventEntry* entry);
    void releaseInboundEventLocked(EventEntry* entry);
    bool isEventFromTrustedSourceLocked(EventEntry* entry);


    // Dispatch state.
    // Dispatch state.
    bool mDispatchEnabled;
    bool mDispatchEnabled;
@@ -971,10 +970,10 @@ private:
            nsecs_t currentTime, ConfigurationChangedEntry* entry);
            nsecs_t currentTime, ConfigurationChangedEntry* entry);
    bool dispatchKeyLocked(
    bool dispatchKeyLocked(
            nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
            nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
            bool dropEvent, nsecs_t* nextWakeupTime);
            DropReason* dropReason, nsecs_t* nextWakeupTime);
    bool dispatchMotionLocked(
    bool dispatchMotionLocked(
            nsecs_t currentTime, MotionEntry* entry,
            nsecs_t currentTime, MotionEntry* entry,
            bool dropEvent, nsecs_t* nextWakeupTime);
            DropReason* dropReason, nsecs_t* nextWakeupTime);
    void dispatchEventToCurrentInputTargetsLocked(
    void dispatchEventToCurrentInputTargetsLocked(
            nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
            nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);


+30 −33
Original line number Original line Diff line number Diff line
@@ -370,7 +370,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
            }
            }
        }
        }
        done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
        done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
                dropReason != DROP_REASON_NOT_DROPPED, nextWakeupTime);
                &dropReason, nextWakeupTime);
        break;
        break;
    }
    }


@@ -380,7 +380,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
            dropReason = DROP_REASON_APP_SWITCH;
            dropReason = DROP_REASON_APP_SWITCH;
        }
        }
        done = dispatchMotionLocked(currentTime, typedEntry,
        done = dispatchMotionLocked(currentTime, typedEntry,
                dropReason != DROP_REASON_NOT_DROPPED, nextWakeupTime);
                &dropReason, nextWakeupTime);
        break;
        break;
    }
    }


@@ -431,6 +431,9 @@ void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropR
    const char* reason;
    const char* reason;
    switch (dropReason) {
    switch (dropReason) {
    case DROP_REASON_POLICY:
    case DROP_REASON_POLICY:
#if DEBUG_INBOUND_EVENT_DETAILS
        LOGD("Dropped event because policy requested that it not be delivered to the application.");
#endif
        reason = "inbound event was dropped because the policy requested that it not be "
        reason = "inbound event was dropped because the policy requested that it not be "
                "delivered to the application";
                "delivered to the application";
        break;
        break;
@@ -473,7 +476,7 @@ bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
    return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
    return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
            && isAppSwitchKeyCode(keyEntry->keyCode)
            && isAppSwitchKeyCode(keyEntry->keyCode)
            && isEventFromTrustedSourceLocked(keyEntry)
            && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
            && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
            && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
}
}


@@ -541,12 +544,6 @@ void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
    mAllocator.releaseEventEntry(entry);
    mAllocator.releaseEventEntry(entry);
}
}


bool InputDispatcher::isEventFromTrustedSourceLocked(EventEntry* entry) {
    InjectionState* injectionState = entry->injectionState;
    return ! injectionState
            || hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid);
}

void InputDispatcher::resetKeyRepeatLocked() {
void InputDispatcher::resetKeyRepeatLocked() {
    if (mKeyRepeatState.lastKeyEntry) {
    if (mKeyRepeatState.lastKeyEntry) {
        mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
        mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
@@ -559,7 +556,8 @@ InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;


    // Reuse the repeated key entry if it is otherwise unreferenced.
    // Reuse the repeated key entry if it is otherwise unreferenced.
    uint32_t policyFlags = entry->policyFlags & (POLICY_FLAG_RAW_MASK | POLICY_FLAG_PASS_TO_USER);
    uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
            | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
    if (entry->refCount == 1) {
    if (entry->refCount == 1) {
        mAllocator.recycleKeyEntry(entry);
        mAllocator.recycleKeyEntry(entry);
        entry->eventTime = currentTime;
        entry->eventTime = currentTime;
@@ -608,19 +606,13 @@ bool InputDispatcher::dispatchConfigurationChangedLocked(


bool InputDispatcher::dispatchKeyLocked(
bool InputDispatcher::dispatchKeyLocked(
        nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
        nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
        bool dropEvent, nsecs_t* nextWakeupTime) {
        DropReason* dropReason, nsecs_t* nextWakeupTime) {
    // Give the policy a chance to intercept the key.
    // Give the policy a chance to intercept the key.
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
        bool trusted;
        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
        if (! dropEvent && mFocusedWindow) {
            trusted = checkInjectionPermission(mFocusedWindow, entry->injectionState);
        } else {
            trusted = isEventFromTrustedSourceLocked(entry);
        }
        if (trusted) {
            CommandEntry* commandEntry = postCommandLocked(
            CommandEntry* commandEntry = postCommandLocked(
                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
            if (! dropEvent && mFocusedWindow) {
            if (mFocusedWindow) {
                commandEntry->inputChannel = mFocusedWindow->inputChannel;
                commandEntry->inputChannel = mFocusedWindow->inputChannel;
            }
            }
            commandEntry->keyEntry = entry;
            commandEntry->keyEntry = entry;
@@ -630,13 +622,16 @@ bool InputDispatcher::dispatchKeyLocked(
            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
        }
        }
    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
        if (*dropReason == DROP_REASON_NOT_DROPPED) {
            *dropReason = DROP_REASON_POLICY;
        }
        resetTargetsLocked();
        resetTargetsLocked();
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED);
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED);
        return true;
        return true;
    }
    }


    // Clean up if dropping the event.
    // Clean up if dropping the event.
    if (dropEvent) {
    if (*dropReason != DROP_REASON_NOT_DROPPED) {
        resetTargetsLocked();
        resetTargetsLocked();
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
        return true;
        return true;
@@ -648,6 +643,7 @@ bool InputDispatcher::dispatchKeyLocked(


        if (entry->repeatCount == 0
        if (entry->repeatCount == 0
                && entry->action == AKEY_EVENT_ACTION_DOWN
                && entry->action == AKEY_EVENT_ACTION_DOWN
                && (entry->policyFlags & POLICY_FLAG_TRUSTED)
                && !entry->isInjected()) {
                && !entry->isInjected()) {
            if (mKeyRepeatState.lastKeyEntry
            if (mKeyRepeatState.lastKeyEntry
                    && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
                    && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
@@ -713,9 +709,9 @@ void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyE
}
}


bool InputDispatcher::dispatchMotionLocked(
bool InputDispatcher::dispatchMotionLocked(
        nsecs_t currentTime, MotionEntry* entry, bool dropEvent, nsecs_t* nextWakeupTime) {
        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
    // Clean up if dropping the event.
    // Clean up if dropping the event.
    if (dropEvent) {
    if (*dropReason != DROP_REASON_NOT_DROPPED) {
        resetTargetsLocked();
        resetTargetsLocked();
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
        return true;
        return true;
@@ -2085,6 +2081,7 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t sou
        return;
        return;
    }
    }


    policyFlags |= POLICY_FLAG_TRUSTED;
    mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
    mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
            keyCode, scanCode, /*byref*/ policyFlags);
            keyCode, scanCode, /*byref*/ policyFlags);


@@ -2130,6 +2127,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t
        return;
        return;
    }
    }


    policyFlags |= POLICY_FLAG_TRUSTED;
    mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
    mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);


    bool needWake;
    bool needWake;
@@ -2263,6 +2261,7 @@ void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t swi
            switchCode, switchValue, policyFlags);
            switchCode, switchValue, policyFlags);
#endif
#endif


    policyFlags |= POLICY_FLAG_TRUSTED;
    mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
    mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
}
}


@@ -2275,7 +2274,11 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
#endif
#endif


    nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
    nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
    bool trusted = hasInjectionPermission(injectorPid, injectorUid);

    uint32_t policyFlags = POLICY_FLAG_INJECTED;
    if (hasInjectionPermission(injectorPid, injectorUid)) {
        policyFlags |= POLICY_FLAG_TRUSTED;
    }


    EventEntry* injectedEntry;
    EventEntry* injectedEntry;
    switch (event->getType()) {
    switch (event->getType()) {
@@ -2291,11 +2294,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
        int32_t flags = keyEvent->getFlags();
        int32_t flags = keyEvent->getFlags();
        int32_t keyCode = keyEvent->getKeyCode();
        int32_t keyCode = keyEvent->getKeyCode();
        int32_t scanCode = keyEvent->getScanCode();
        int32_t scanCode = keyEvent->getScanCode();
        uint32_t policyFlags = POLICY_FLAG_INJECTED;
        if (trusted) {
        mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
        mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
                keyCode, scanCode, /*byref*/ policyFlags);
                keyCode, scanCode, /*byref*/ policyFlags);
        }


        mLock.lock();
        mLock.lock();
        injectedEntry = mAllocator.obtainKeyEntry(eventTime, deviceId, keyEvent->getSource(),
        injectedEntry = mAllocator.obtainKeyEntry(eventTime, deviceId, keyEvent->getSource(),
@@ -2314,10 +2314,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
        }
        }


        nsecs_t eventTime = motionEvent->getEventTime();
        nsecs_t eventTime = motionEvent->getEventTime();
        uint32_t policyFlags = POLICY_FLAG_INJECTED;
        if (trusted) {
        mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
        mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
        }


        mLock.lock();
        mLock.lock();
        const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
        const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
+13 −2
Original line number Original line Diff line number Diff line
@@ -1123,6 +1123,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    @Override
    @Override
    public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
    public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags,
            int keyCode, int metaState, int repeatCount, int policyFlags) {
            int keyCode, int metaState, int repeatCount, int policyFlags) {
        if ((policyFlags & WindowManagerPolicy.FLAG_TRUSTED) == 0) {
            return false;
        }

        final boolean keyguardOn = keyguardOn();
        final boolean keyguardOn = keyguardOn();
        final boolean down = (action == KeyEvent.ACTION_DOWN);
        final boolean down = (action == KeyEvent.ACTION_DOWN);
        final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0);
        final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0);
@@ -1831,6 +1835,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
    public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
            int policyFlags, boolean isScreenOn) {
            int policyFlags, boolean isScreenOn) {
        int result = ACTION_PASS_TO_USER;
        int result = ACTION_PASS_TO_USER;
        if ((policyFlags & WindowManagerPolicy.FLAG_TRUSTED) == 0) {
            return result;
        }

        if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) {
            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
        }


        final boolean isWakeKey = (policyFlags
        final boolean isWakeKey = (policyFlags
                & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
                & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
Loading