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

Commit b14c3e7e authored by Chris Tate's avatar Chris Tate Committed by Android (Google) Code Review
Browse files

Merge "Native input event dispatching." into gingerbread

parents e1b6c6fe 50de30a5
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -87,6 +87,9 @@ enum {
    // Indicates that the screen was dim when the event was received and the event
    // should brighten the device.
    POLICY_FLAG_BRIGHT_HERE = 0x20000000,

    // Indicates that the dispatcher should call back into the policy before dispatching. */
    POLICY_FLAG_INTERCEPT_DISPATCH = 0x40000000,
};

/*
+16 −4
Original line number Diff line number Diff line
@@ -126,21 +126,21 @@ public:
    /* Gets the key repeat timeout or -1 if automatic key repeating is disabled. */
    virtual nsecs_t getKeyRepeatTimeout() = 0;

    /* Gets the input targets for a key event.
    /* Waits for key event input targets to become available.
     * If the event is being injected, injectorPid and injectorUid should specify the
     * process id and used id of the injecting application, otherwise they should both
     * be -1.
     * Returns one of the INPUT_EVENT_INJECTION_XXX constants. */
    virtual int32_t getKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
    virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
            int32_t injectorPid, int32_t injectorUid,
            Vector<InputTarget>& outTargets) = 0;

    /* Gets the input targets for a motion event.
    /* Waits for motion event targets to become available.
     * If the event is being injected, injectorPid and injectorUid should specify the
     * process id and used id of the injecting application, otherwise they should both
     * be -1.
     * Returns one of the INPUT_EVENT_INJECTION_XXX constants. */
    virtual int32_t getMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
    virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
            int32_t injectorPid, int32_t injectorUid,
            Vector<InputTarget>& outTargets) = 0;
};
@@ -186,6 +186,16 @@ public:
    virtual int32_t injectInputEvent(const InputEvent* event,
            int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis) = 0;

    /* Preempts input dispatch in progress by making pending synchronous
     * dispatches asynchronous instead.  This method is generally called during a focus
     * transition from one application to the next so as to enable the new application
     * to start receiving input as soon as possible without having to wait for the
     * old application to finish up.
     *
     * This method may be called on any thread (usually by the input manager).
     */
    virtual void preemptInputDispatch() = 0;

    /* Registers or unregister input channels that may be used as targets for input events.
     *
     * These methods may be called on any thread (usually by the input manager).
@@ -233,6 +243,8 @@ public:
    virtual int32_t injectInputEvent(const InputEvent* event,
            int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis);

    virtual void preemptInputDispatch();

    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel);
    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);

+10 −0
Original line number Diff line number Diff line
@@ -87,6 +87,14 @@ public:
    virtual int32_t injectInputEvent(const InputEvent* event,
            int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis) = 0;

    /* Preempts input dispatch in progress by making pending synchronous
     * dispatches asynchronous instead.  This method is generally called during a focus
     * transition from one application to the next so as to enable the new application
     * to start receiving input as soon as possible without having to wait for the
     * old application to finish up.
     */
    virtual void preemptInputDispatch() = 0;

    /* Gets input device configuration. */
    virtual void getInputConfiguration(InputConfiguration* outConfiguration) const = 0;

@@ -130,6 +138,8 @@ public:
    virtual int32_t injectInputEvent(const InputEvent* event,
            int32_t injectorPid, int32_t injectorUid, bool sync, int32_t timeoutMillis);

    virtual void preemptInputDispatch();

    virtual void getInputConfiguration(InputConfiguration* outConfiguration) const;
    virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
            int32_t scanCode) const;
+5 −1
Original line number Diff line number Diff line
@@ -361,7 +361,11 @@ public:

        // The input dispatcher should add POLICY_FLAG_BRIGHT_HERE to the policy flags it
        // passes through the dispatch pipeline.
        ACTION_BRIGHT_HERE = 0x00000008
        ACTION_BRIGHT_HERE = 0x00000008,

        // The input dispatcher should add POLICY_FLAG_INTERCEPT_DISPATCH to the policy flags
        // it passed through the dispatch pipeline.
        ACTION_INTERCEPT_DISPATCH = 0x00000010
    };

    /* Describes a virtual key. */
+63 −23
Original line number Diff line number Diff line
@@ -8,25 +8,25 @@
//#define LOG_NDEBUG 0

// Log detailed debug messages about each inbound event notification to the dispatcher.
#define DEBUG_INBOUND_EVENT_DETAILS 1
#define DEBUG_INBOUND_EVENT_DETAILS 0

// Log detailed debug messages about each outbound event processed by the dispatcher.
#define DEBUG_OUTBOUND_EVENT_DETAILS 1
#define DEBUG_OUTBOUND_EVENT_DETAILS 0

// Log debug messages about batching.
#define DEBUG_BATCHING 1
#define DEBUG_BATCHING 0

// Log debug messages about the dispatch cycle.
#define DEBUG_DISPATCH_CYCLE 1
#define DEBUG_DISPATCH_CYCLE 0

// Log debug messages about registrations.
#define DEBUG_REGISTRATION 1
#define DEBUG_REGISTRATION 0

// Log debug messages about performance statistics.
#define DEBUG_PERFORMANCE_STATISTICS 1
#define DEBUG_PERFORMANCE_STATISTICS 0

// Log debug messages about input event injection.
#define DEBUG_INJECTION 1
#define DEBUG_INJECTION 0

#include <cutils/log.h>
#include <ui/InputDispatcher.h>
@@ -249,9 +249,7 @@ void InputDispatcher::processKeyLockedInterruptible(
            entry->downTime);
#endif

    // TODO: Poke user activity.

    if (entry->action == KEY_EVENT_ACTION_DOWN) {
    if (entry->action == KEY_EVENT_ACTION_DOWN && ! entry->isInjected()) {
        if (mKeyRepeatState.lastKeyEntry
                && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
            // We have seen two identical key downs in a row which indicates that the device
@@ -277,14 +275,24 @@ void InputDispatcher::processKeyLockedInterruptible(

void InputDispatcher::processKeyRepeatLockedInterruptible(
        nsecs_t currentTime, nsecs_t keyRepeatTimeout) {
    // TODO Old WindowManagerServer code sniffs the input queue for following key up
    //      events and drops the repeat if one is found.  We should do something similar.
    //      One good place to do it is in notifyKey as soon as the key up enters the
    //      inbound event queue.
    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;

    // Search the inbound queue for a key up corresponding to this device.
    // It doesn't make sense to generate a key repeat event if the key is already up.
    for (EventEntry* queuedEntry = mInboundQueue.head.next;
            queuedEntry != & mInboundQueue.tail; queuedEntry = entry->next) {
        if (queuedEntry->type == EventEntry::TYPE_KEY) {
            KeyEntry* queuedKeyEntry = static_cast<KeyEntry*>(queuedEntry);
            if (queuedKeyEntry->deviceId == entry->deviceId
                    && entry->action == KEY_EVENT_ACTION_UP) {
                resetKeyRepeatLocked();
                return;
            }
        }
    }

    // Synthesize a key repeat after the repeat timeout expired.
    // We reuse the previous key entry if otherwise unreferenced.
    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
    // Reuse the repeated key entry if it is otherwise unreferenced.
    uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
    if (entry->refCount == 1) {
        entry->eventTime = currentTime;
@@ -366,7 +374,7 @@ void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(
            entry->downTime, entry->eventTime);

    mCurrentInputTargets.clear();
    int32_t injectionResult = mPolicy->getKeyEventTargets(& mReusableKeyEvent,
    int32_t injectionResult = mPolicy->waitForKeyEventTargets(& mReusableKeyEvent,
            entry->policyFlags, entry->injectorPid, entry->injectorUid,
            mCurrentInputTargets);

@@ -375,8 +383,10 @@ void InputDispatcher::identifyInputTargetsAndDispatchKeyLockedInterruptible(

    setInjectionResultLocked(entry, injectionResult);

    if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
        dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
    }
}

void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
        nsecs_t currentTime, MotionEntry* entry) {
@@ -395,7 +405,7 @@ void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
            entry->firstSample.pointerCoords);

    mCurrentInputTargets.clear();
    int32_t injectionResult = mPolicy->getMotionEventTargets(& mReusableMotionEvent,
    int32_t injectionResult = mPolicy->waitForMotionEventTargets(& mReusableMotionEvent,
            entry->policyFlags, entry->injectorPid, entry->injectorUid,
            mCurrentInputTargets);

@@ -404,8 +414,10 @@ void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(

    setInjectionResultLocked(entry, injectionResult);

    if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED) {
        dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
    }
}

void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
        EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
@@ -1253,9 +1265,37 @@ void InputDispatcher::resetKeyRepeatLocked() {
    }
}

void InputDispatcher::preemptInputDispatch() {
#if DEBUG_DISPATCH_CYCLE
    LOGD("preemptInputDispatch");
#endif

    bool preemptedOne = false;
    { // acquire lock
        AutoMutex _l(mLock);

        for (size_t i = 0; i < mActiveConnections.size(); i++) {
            Connection* connection = mActiveConnections[i];
            if (connection->hasPendingSyncTarget()) {
#if DEBUG_DISPATCH_CYCLE
                LOGD("channel '%s' ~ Preempted pending synchronous dispatch",
                        connection->getInputChannelName());
#endif
                connection->outboundQueue.tail.prev->targetFlags &= ~ InputTarget::FLAG_SYNC;
                preemptedOne = true;
            }
        }
    } // release lock

    if (preemptedOne) {
        // Wake up the poll loop so it can get a head start dispatching the next event.
        mPollLoop->wake();
    }
}

status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
#if DEBUG_REGISTRATION
    LOGD("channel '%s' - Registered", inputChannel->getName().string());
    LOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().string());
#endif

    int receiveFd;
@@ -1288,7 +1328,7 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan

status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
#if DEBUG_REGISTRATION
    LOGD("channel '%s' - Unregistered", inputChannel->getName().string());
    LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
#endif

    int32_t receiveFd;
Loading