Loading include/ui/Input.h +3 −0 Original line number Diff line number Diff line Loading @@ -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, }; /* Loading include/ui/InputDispatcher.h +16 −4 Original line number Diff line number Diff line Loading @@ -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; }; Loading Loading @@ -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). Loading Loading @@ -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); Loading include/ui/InputManager.h +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading include/ui/InputReader.h +5 −1 Original line number Diff line number Diff line Loading @@ -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. */ Loading libs/ui/InputDispatcher.cpp +63 −23 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading @@ -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; Loading Loading @@ -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); Loading @@ -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) { Loading @@ -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); Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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 Loading
include/ui/Input.h +3 −0 Original line number Diff line number Diff line Loading @@ -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, }; /* Loading
include/ui/InputDispatcher.h +16 −4 Original line number Diff line number Diff line Loading @@ -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; }; Loading Loading @@ -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). Loading Loading @@ -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); Loading
include/ui/InputManager.h +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading
include/ui/InputReader.h +5 −1 Original line number Diff line number Diff line Loading @@ -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. */ Loading
libs/ui/InputDispatcher.cpp +63 −23 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading @@ -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; Loading Loading @@ -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); Loading @@ -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) { Loading @@ -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); Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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