Loading services/inputflinger/dispatcher/InputDispatcher.cpp +55 −30 Original line number Original line Diff line number Diff line Loading @@ -620,6 +620,33 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { } } } } /** * Return true if the events preceding this incoming motion event should be dropped * Return false otherwise (the default behaviour) */ bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) { bool isPointerDownEvent = motionEntry.action == AMOTION_EVENT_ACTION_DOWN && (motionEntry.source & AINPUT_SOURCE_CLASS_POINTER); if (isPointerDownEvent && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY && mInputTargetWaitApplicationToken != nullptr) { int32_t displayId = motionEntry.displayId; int32_t x = static_cast<int32_t>( motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = static_cast<int32_t>( motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); if (touchedWindowHandle != nullptr && touchedWindowHandle->getApplicationToken() != mInputTargetWaitApplicationToken) { // User touched a different application than the one we are waiting on. // Flag the event, and start pruning the input queue. ALOGI("Pruning input queue because user touched a different application"); return true; } } return false; } bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { bool needWake = mInboundQueue.empty(); bool needWake = mInboundQueue.empty(); mInboundQueue.push_back(entry); mInboundQueue.push_back(entry); Loading Loading @@ -653,32 +680,18 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { // decides to touch a window in a different application. // decides to touch a window in a different application. // If the application takes too long to catch up then we drop all events preceding // If the application takes too long to catch up then we drop all events preceding // the touch into the other window. // the touch into the other window. MotionEntry* motionEntry = static_cast<MotionEntry*>(entry); if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(*entry))) { if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN && mNextUnblockedEvent = entry; (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY && mInputTargetWaitApplicationToken != nullptr) { int32_t displayId = motionEntry->displayId; int32_t x = int32_t(motionEntry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = int32_t(motionEntry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); if (touchedWindowHandle != nullptr && touchedWindowHandle->getApplicationToken() != mInputTargetWaitApplicationToken) { // User touched a different application than the one we are waiting on. // Flag the event, and start pruning the input queue. mNextUnblockedEvent = motionEntry; needWake = true; needWake = true; } } break; } } case EventEntry::Type::FOCUS: { LOG_ALWAYS_FATAL("Focus events should be inserted using enqueueFocusEventLocked"); break; break; } } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::DEVICE_RESET: { case EventEntry::Type::FOCUS: { // nothing to do // nothing to do break; break; } } Loading Loading @@ -980,9 +993,24 @@ bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime, DeviceReset } } void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) { void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) { if (mPendingEvent != nullptr) { // Move the pending event to the front of the queue. This will give the chance // for the pending event to get dispatched to the newly focused window mInboundQueue.push_front(mPendingEvent); mPendingEvent = nullptr; } FocusEntry* focusEntry = FocusEntry* focusEntry = new FocusEntry(mIdGenerator.nextId(), now(), window.getToken(), hasFocus); new FocusEntry(mIdGenerator.nextId(), now(), window.getToken(), hasFocus); enqueueInboundEventLocked(focusEntry); // This event should go to the front of the queue, but behind all other focus events // Find the last focus event, and insert right after it std::deque<EventEntry*>::reverse_iterator it = std::find_if(mInboundQueue.rbegin(), mInboundQueue.rend(), [](EventEntry* event) { return event->type == EventEntry::Type::FOCUS; }); // Maintain the order of focus events. Insert the entry after all other focus events. mInboundQueue.insert(it.base(), focusEntry); } } void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) { void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) { Loading Loading @@ -2108,15 +2136,12 @@ std::string InputDispatcher::getApplicationWindowLabel( const sp<InputWindowHandle>& windowHandle) { const sp<InputWindowHandle>& windowHandle) { if (applicationHandle != nullptr) { if (applicationHandle != nullptr) { if (windowHandle != nullptr) { if (windowHandle != nullptr) { std::string label(applicationHandle->getName()); return applicationHandle->getName() + " - " + windowHandle->getName(); label += " - "; label += windowHandle->getName(); return label; } else { } else { return applicationHandle->getName(); return applicationHandle->getName(); } } } else if (windowHandle != nullptr) { } else if (windowHandle != nullptr) { return windowHandle->getName(); return windowHandle->getInfo()->applicationInfo.name + " - " + windowHandle->getName(); } else { } else { return "<unknown application or window>"; return "<unknown application or window>"; } } Loading Loading @@ -4620,7 +4645,7 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c } } DispatchEntry* dispatchEntry = *dispatchEntryIt; DispatchEntry* dispatchEntry = *dispatchEntryIt; nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime; const nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime; if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) { if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) { std::string msg = std::string msg = StringPrintf("Window '%s' spent %0.1fms processing the last input event: ", StringPrintf("Window '%s' spent %0.1fms processing the last input event: ", Loading @@ -4644,7 +4669,7 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c } } // Dequeue the event and start the next cycle. // Dequeue the event and start the next cycle. // Note that because the lock might have been released, it is possible that the // Because the lock might have been released, it is possible that the // contents of the wait queue to have been drained, so we need to double-check // contents of the wait queue to have been drained, so we need to double-check // a few things. // a few things. dispatchEntryIt = connection->findWaitQueueEntry(seq); dispatchEntryIt = connection->findWaitQueueEntry(seq); Loading services/inputflinger/dispatcher/InputDispatcher.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -345,6 +345,8 @@ private: bool mInputTargetWaitTimeoutExpired GUARDED_BY(mLock); bool mInputTargetWaitTimeoutExpired GUARDED_BY(mLock); sp<IBinder> mInputTargetWaitApplicationToken GUARDED_BY(mLock); sp<IBinder> mInputTargetWaitApplicationToken GUARDED_BY(mLock); bool shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) REQUIRES(mLock); // Contains the last window which received a hover event. // Contains the last window which received a hover event. sp<InputWindowHandle> mLastHoverWindowHandle GUARDED_BY(mLock); sp<InputWindowHandle> mLastHoverWindowHandle GUARDED_BY(mLock); Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +55 −30 Original line number Original line Diff line number Diff line Loading @@ -620,6 +620,33 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { } } } } /** * Return true if the events preceding this incoming motion event should be dropped * Return false otherwise (the default behaviour) */ bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) { bool isPointerDownEvent = motionEntry.action == AMOTION_EVENT_ACTION_DOWN && (motionEntry.source & AINPUT_SOURCE_CLASS_POINTER); if (isPointerDownEvent && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY && mInputTargetWaitApplicationToken != nullptr) { int32_t displayId = motionEntry.displayId; int32_t x = static_cast<int32_t>( motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = static_cast<int32_t>( motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); if (touchedWindowHandle != nullptr && touchedWindowHandle->getApplicationToken() != mInputTargetWaitApplicationToken) { // User touched a different application than the one we are waiting on. // Flag the event, and start pruning the input queue. ALOGI("Pruning input queue because user touched a different application"); return true; } } return false; } bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { bool needWake = mInboundQueue.empty(); bool needWake = mInboundQueue.empty(); mInboundQueue.push_back(entry); mInboundQueue.push_back(entry); Loading Loading @@ -653,32 +680,18 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) { // decides to touch a window in a different application. // decides to touch a window in a different application. // If the application takes too long to catch up then we drop all events preceding // If the application takes too long to catch up then we drop all events preceding // the touch into the other window. // the touch into the other window. MotionEntry* motionEntry = static_cast<MotionEntry*>(entry); if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(*entry))) { if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN && mNextUnblockedEvent = entry; (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY && mInputTargetWaitApplicationToken != nullptr) { int32_t displayId = motionEntry->displayId; int32_t x = int32_t(motionEntry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X)); int32_t y = int32_t(motionEntry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y)); sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y); if (touchedWindowHandle != nullptr && touchedWindowHandle->getApplicationToken() != mInputTargetWaitApplicationToken) { // User touched a different application than the one we are waiting on. // Flag the event, and start pruning the input queue. mNextUnblockedEvent = motionEntry; needWake = true; needWake = true; } } break; } } case EventEntry::Type::FOCUS: { LOG_ALWAYS_FATAL("Focus events should be inserted using enqueueFocusEventLocked"); break; break; } } case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::CONFIGURATION_CHANGED: case EventEntry::Type::DEVICE_RESET: case EventEntry::Type::DEVICE_RESET: { case EventEntry::Type::FOCUS: { // nothing to do // nothing to do break; break; } } Loading Loading @@ -980,9 +993,24 @@ bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime, DeviceReset } } void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) { void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) { if (mPendingEvent != nullptr) { // Move the pending event to the front of the queue. This will give the chance // for the pending event to get dispatched to the newly focused window mInboundQueue.push_front(mPendingEvent); mPendingEvent = nullptr; } FocusEntry* focusEntry = FocusEntry* focusEntry = new FocusEntry(mIdGenerator.nextId(), now(), window.getToken(), hasFocus); new FocusEntry(mIdGenerator.nextId(), now(), window.getToken(), hasFocus); enqueueInboundEventLocked(focusEntry); // This event should go to the front of the queue, but behind all other focus events // Find the last focus event, and insert right after it std::deque<EventEntry*>::reverse_iterator it = std::find_if(mInboundQueue.rbegin(), mInboundQueue.rend(), [](EventEntry* event) { return event->type == EventEntry::Type::FOCUS; }); // Maintain the order of focus events. Insert the entry after all other focus events. mInboundQueue.insert(it.base(), focusEntry); } } void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) { void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) { Loading Loading @@ -2108,15 +2136,12 @@ std::string InputDispatcher::getApplicationWindowLabel( const sp<InputWindowHandle>& windowHandle) { const sp<InputWindowHandle>& windowHandle) { if (applicationHandle != nullptr) { if (applicationHandle != nullptr) { if (windowHandle != nullptr) { if (windowHandle != nullptr) { std::string label(applicationHandle->getName()); return applicationHandle->getName() + " - " + windowHandle->getName(); label += " - "; label += windowHandle->getName(); return label; } else { } else { return applicationHandle->getName(); return applicationHandle->getName(); } } } else if (windowHandle != nullptr) { } else if (windowHandle != nullptr) { return windowHandle->getName(); return windowHandle->getInfo()->applicationInfo.name + " - " + windowHandle->getName(); } else { } else { return "<unknown application or window>"; return "<unknown application or window>"; } } Loading Loading @@ -4620,7 +4645,7 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c } } DispatchEntry* dispatchEntry = *dispatchEntryIt; DispatchEntry* dispatchEntry = *dispatchEntryIt; nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime; const nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime; if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) { if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) { std::string msg = std::string msg = StringPrintf("Window '%s' spent %0.1fms processing the last input event: ", StringPrintf("Window '%s' spent %0.1fms processing the last input event: ", Loading @@ -4644,7 +4669,7 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c } } // Dequeue the event and start the next cycle. // Dequeue the event and start the next cycle. // Note that because the lock might have been released, it is possible that the // Because the lock might have been released, it is possible that the // contents of the wait queue to have been drained, so we need to double-check // contents of the wait queue to have been drained, so we need to double-check // a few things. // a few things. dispatchEntryIt = connection->findWaitQueueEntry(seq); dispatchEntryIt = connection->findWaitQueueEntry(seq); Loading
services/inputflinger/dispatcher/InputDispatcher.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -345,6 +345,8 @@ private: bool mInputTargetWaitTimeoutExpired GUARDED_BY(mLock); bool mInputTargetWaitTimeoutExpired GUARDED_BY(mLock); sp<IBinder> mInputTargetWaitApplicationToken GUARDED_BY(mLock); sp<IBinder> mInputTargetWaitApplicationToken GUARDED_BY(mLock); bool shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) REQUIRES(mLock); // Contains the last window which received a hover event. // Contains the last window which received a hover event. sp<InputWindowHandle> mLastHoverWindowHandle GUARDED_BY(mLock); sp<InputWindowHandle> mLastHoverWindowHandle GUARDED_BY(mLock); Loading