diff options
-rw-r--r-- | services/inputflinger/dispatcher/Connection.cpp | 9 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/Connection.h | 6 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/Entry.h | 4 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 116 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.h | 8 |
5 files changed, 70 insertions, 73 deletions
diff --git a/services/inputflinger/dispatcher/Connection.cpp b/services/inputflinger/dispatcher/Connection.cpp index ed95de787c..f304712e8c 100644 --- a/services/inputflinger/dispatcher/Connection.cpp +++ b/services/inputflinger/dispatcher/Connection.cpp @@ -38,13 +38,4 @@ const std::string Connection::getWindowName() const { return "?"; } -std::deque<DispatchEntry*>::iterator Connection::findWaitQueueEntry(uint32_t seq) { - for (std::deque<DispatchEntry*>::iterator it = waitQueue.begin(); it != waitQueue.end(); it++) { - if ((*it)->seq == seq) { - return it; - } - } - return waitQueue.end(); -} - } // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/Connection.h b/services/inputflinger/dispatcher/Connection.h index 2929d61871..c17baea0e5 100644 --- a/services/inputflinger/dispatcher/Connection.h +++ b/services/inputflinger/dispatcher/Connection.h @@ -53,11 +53,11 @@ public: bool responsive = true; // Queue of events that need to be published to the connection. - std::deque<DispatchEntry*> outboundQueue; + std::deque<std::unique_ptr<DispatchEntry>> outboundQueue; // Queue of events that have been published to the connection but that have not // yet received a "finished" response from the application. - std::deque<DispatchEntry*> waitQueue; + std::deque<std::unique_ptr<DispatchEntry>> waitQueue; Connection(const std::shared_ptr<InputChannel>& inputChannel, bool monitor, const IdGenerator& idGenerator); @@ -65,8 +65,6 @@ public: inline const std::string getInputChannelName() const { return inputChannel->getName(); } const std::string getWindowName() const; - - std::deque<DispatchEntry*>::iterator findWaitQueueEntry(uint32_t seq); }; } // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index dd4aab85f5..98e2507a94 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -226,7 +226,7 @@ struct DispatchEntry { const uint32_t seq; // unique sequence number, never 0 std::shared_ptr<EventEntry> eventEntry; // the event to dispatch - ftl::Flags<InputTarget::Flags> targetFlags; + const ftl::Flags<InputTarget::Flags> targetFlags; ui::Transform transform; ui::Transform rawTransform; float globalScaleFactor; @@ -244,6 +244,8 @@ struct DispatchEntry { DispatchEntry(std::shared_ptr<EventEntry> eventEntry, ftl::Flags<InputTarget::Flags> targetFlags, const ui::Transform& transform, const ui::Transform& rawTransform, float globalScaleFactor); + DispatchEntry(const DispatchEntry&) = delete; + DispatchEntry& operator=(const DispatchEntry&) = delete; inline bool hasForegroundTarget() const { return targetFlags.test(InputTarget::Flags::FOREGROUND); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 8e20eaf954..42516828c5 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -271,7 +271,8 @@ std::string dumpRegion(const Region& region) { return dump; } -std::string dumpQueue(const std::deque<DispatchEntry*>& queue, nsecs_t currentTime) { +std::string dumpQueue(const std::deque<std::unique_ptr<DispatchEntry>>& queue, + nsecs_t currentTime) { constexpr size_t maxEntries = 50; // max events to print constexpr size_t skipBegin = maxEntries / 2; const size_t skipEnd = queue.size() - maxEntries / 2; @@ -492,8 +493,8 @@ bool shouldReportFinishedEvent(const DispatchEntry& dispatchEntry, const Connect */ bool isConnectionResponsive(const Connection& connection) { const nsecs_t currentTime = now(); - for (const DispatchEntry* entry : connection.waitQueue) { - if (entry->timeoutTime < currentTime) { + for (const auto& dispatchEntry : connection.waitQueue) { + if (dispatchEntry->timeoutTime < currentTime) { return false; } } @@ -3415,7 +3416,7 @@ void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connectio } // Enqueue the dispatch entry. - connection->outboundQueue.push_back(dispatchEntry.release()); + connection->outboundQueue.emplace_back(std::move(dispatchEntry)); traceOutboundQueueLength(*connection); } @@ -3584,7 +3585,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, } while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) { - DispatchEntry* dispatchEntry = connection->outboundQueue.front(); + std::unique_ptr<DispatchEntry>& dispatchEntry = connection->outboundQueue.front(); dispatchEntry->deliveryTime = currentTime; const std::chrono::nanoseconds timeout = getDispatchingTimeoutLocked(connection); dispatchEntry->timeoutTime = currentTime + timeout.count(); @@ -3699,14 +3700,12 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, } // Re-enqueue the event on the wait queue. - connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(), - connection->outboundQueue.end(), - dispatchEntry)); + const nsecs_t timeoutTime = dispatchEntry->timeoutTime; + connection->waitQueue.emplace_back(std::move(dispatchEntry)); + connection->outboundQueue.erase(connection->outboundQueue.begin()); traceOutboundQueueLength(*connection); - connection->waitQueue.push_back(dispatchEntry); if (connection->responsive) { - mAnrTracker.insert(dispatchEntry->timeoutTime, - connection->inputChannel->getConnectionToken()); + mAnrTracker.insert(timeoutTime, connection->inputChannel->getConnectionToken()); } traceWaitQueueLength(*connection); } @@ -3805,19 +3804,17 @@ void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime, } } -void InputDispatcher::drainDispatchQueue(std::deque<DispatchEntry*>& queue) { +void InputDispatcher::drainDispatchQueue(std::deque<std::unique_ptr<DispatchEntry>>& queue) { while (!queue.empty()) { - DispatchEntry* dispatchEntry = queue.front(); + releaseDispatchEntry(std::move(queue.front())); queue.pop_front(); - releaseDispatchEntry(dispatchEntry); } } -void InputDispatcher::releaseDispatchEntry(DispatchEntry* dispatchEntry) { +void InputDispatcher::releaseDispatchEntry(std::unique_ptr<DispatchEntry> dispatchEntry) { if (dispatchEntry->hasForegroundTarget()) { decrementPendingForegroundDispatches(*(dispatchEntry->eventEntry)); } - delete dispatchEntry; } int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) { @@ -6065,43 +6062,52 @@ void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime, uint32_t seq, bool handled, nsecs_t consumeTime) { // Handle post-event policy actions. - std::deque<DispatchEntry*>::iterator dispatchEntryIt = connection->findWaitQueueEntry(seq); - if (dispatchEntryIt == connection->waitQueue.end()) { - return; - } - DispatchEntry* dispatchEntry = *dispatchEntryIt; - const nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime; - if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) { - ALOGI("%s spent %" PRId64 "ms processing %s", connection->getWindowName().c_str(), - ns2ms(eventDuration), dispatchEntry->eventEntry->getDescription().c_str()); - } - if (shouldReportFinishedEvent(*dispatchEntry, *connection)) { - mLatencyTracker.trackFinishedEvent(dispatchEntry->eventEntry->id, - connection->inputChannel->getConnectionToken(), - dispatchEntry->deliveryTime, consumeTime, finishTime); - } - bool restartEvent; - if (dispatchEntry->eventEntry->type == EventEntry::Type::KEY) { - KeyEntry& keyEntry = static_cast<KeyEntry&>(*(dispatchEntry->eventEntry)); - restartEvent = - afterKeyEventLockedInterruptable(connection, dispatchEntry, keyEntry, handled); - } else if (dispatchEntry->eventEntry->type == EventEntry::Type::MOTION) { - MotionEntry& motionEntry = static_cast<MotionEntry&>(*(dispatchEntry->eventEntry)); - restartEvent = afterMotionEventLockedInterruptable(connection, dispatchEntry, motionEntry, - handled); - } else { - restartEvent = false; - } + + { // Start critical section + auto dispatchEntryIt = + std::find_if(connection->waitQueue.begin(), connection->waitQueue.end(), + [seq](auto& e) { return e->seq == seq; }); + if (dispatchEntryIt == connection->waitQueue.end()) { + return; + } + + DispatchEntry& dispatchEntry = **dispatchEntryIt; + + const nsecs_t eventDuration = finishTime - dispatchEntry.deliveryTime; + if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) { + ALOGI("%s spent %" PRId64 "ms processing %s", connection->getWindowName().c_str(), + ns2ms(eventDuration), dispatchEntry.eventEntry->getDescription().c_str()); + } + if (shouldReportFinishedEvent(dispatchEntry, *connection)) { + mLatencyTracker.trackFinishedEvent(dispatchEntry.eventEntry->id, + connection->inputChannel->getConnectionToken(), + dispatchEntry.deliveryTime, consumeTime, finishTime); + } + + if (dispatchEntry.eventEntry->type == EventEntry::Type::KEY) { + KeyEntry& keyEntry = static_cast<KeyEntry&>(*(dispatchEntry.eventEntry)); + restartEvent = + afterKeyEventLockedInterruptable(connection, dispatchEntry, keyEntry, handled); + } else if (dispatchEntry.eventEntry->type == EventEntry::Type::MOTION) { + MotionEntry& motionEntry = static_cast<MotionEntry&>(*(dispatchEntry.eventEntry)); + restartEvent = afterMotionEventLockedInterruptable(connection, dispatchEntry, + motionEntry, handled); + } else { + restartEvent = false; + } + } // End critical section: The -LockedInterruptable methods may have released the lock. // Dequeue the event and start the next cycle. // 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 // a few things. - dispatchEntryIt = connection->findWaitQueueEntry(seq); - if (dispatchEntryIt != connection->waitQueue.end()) { - dispatchEntry = *dispatchEntryIt; - connection->waitQueue.erase(dispatchEntryIt); + auto entryIt = std::find_if(connection->waitQueue.begin(), connection->waitQueue.end(), + [seq](auto& e) { return e->seq == seq; }); + if (entryIt != connection->waitQueue.end()) { + std::unique_ptr<DispatchEntry> dispatchEntry = std::move(*entryIt); + connection->waitQueue.erase(entryIt); + const sp<IBinder>& connectionToken = connection->inputChannel->getConnectionToken(); mAnrTracker.erase(dispatchEntry->timeoutTime, connectionToken); if (!connection->responsive) { @@ -6113,10 +6119,10 @@ void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime, } traceWaitQueueLength(*connection); if (restartEvent && connection->status == Connection::Status::NORMAL) { - connection->outboundQueue.push_front(dispatchEntry); + connection->outboundQueue.emplace_front(std::move(dispatchEntry)); traceOutboundQueueLength(*connection); } else { - releaseDispatchEntry(dispatchEntry); + releaseDispatchEntry(std::move(dispatchEntry)); } } @@ -6160,13 +6166,13 @@ void InputDispatcher::onAnrLocked(const std::shared_ptr<Connection>& connection) * processes the events linearly. So providing information about the oldest entry seems to be * most useful. */ - DispatchEntry* oldestEntry = *connection->waitQueue.begin(); - const nsecs_t currentWait = now() - oldestEntry->deliveryTime; + DispatchEntry& oldestEntry = *connection->waitQueue.front(); + const nsecs_t currentWait = now() - oldestEntry.deliveryTime; std::string reason = android::base::StringPrintf("%s is not responding. Waited %" PRId64 "ms for %s", connection->inputChannel->getName().c_str(), ns2ms(currentWait), - oldestEntry->eventEntry->getDescription().c_str()); + oldestEntry.eventEntry->getDescription().c_str()); sp<IBinder> connectionToken = connection->inputChannel->getConnectionToken(); updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason); @@ -6303,7 +6309,7 @@ void InputDispatcher::processConnectionResponsiveLocked(const Connection& connec } bool InputDispatcher::afterKeyEventLockedInterruptable( - const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry, + const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry, KeyEntry& keyEntry, bool handled) { if (keyEntry.flags & AKEY_EVENT_FLAG_FALLBACK) { if (!handled) { @@ -6321,7 +6327,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable( connection->inputState.removeFallbackKey(originalKeyCode); } - if (handled || !dispatchEntry->hasForegroundTarget()) { + if (handled || !dispatchEntry.hasForegroundTarget()) { // If the application handles the original key for which we previously // generated a fallback or if the window is not a foreground window, // then cancel the associated fallback key, if any. @@ -6488,7 +6494,7 @@ bool InputDispatcher::afterKeyEventLockedInterruptable( } bool InputDispatcher::afterMotionEventLockedInterruptable( - const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry, + const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry, MotionEntry& motionEntry, bool handled) { return false; } diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 67705b9392..62e2d583d6 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -598,8 +598,8 @@ private: void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const std::shared_ptr<Connection>& connection, bool notify) REQUIRES(mLock); - void drainDispatchQueue(std::deque<DispatchEntry*>& queue); - void releaseDispatchEntry(DispatchEntry* dispatchEntry); + void drainDispatchQueue(std::deque<std::unique_ptr<DispatchEntry>>& queue); + void releaseDispatchEntry(std::unique_ptr<DispatchEntry> dispatchEntry); int handleReceiveCallback(int events, sp<IBinder> connectionToken); // The action sent should only be of type AMOTION_EVENT_* void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action, @@ -664,10 +664,10 @@ private: REQUIRES(mLock); std::map<int32_t /*displayId*/, InputVerifier> mVerifiersByDisplay; bool afterKeyEventLockedInterruptable(const std::shared_ptr<Connection>& connection, - DispatchEntry* dispatchEntry, KeyEntry& keyEntry, + DispatchEntry& dispatchEntry, KeyEntry& keyEntry, bool handled) REQUIRES(mLock); bool afterMotionEventLockedInterruptable(const std::shared_ptr<Connection>& connection, - DispatchEntry* dispatchEntry, MotionEntry& motionEntry, + DispatchEntry& dispatchEntry, MotionEntry& motionEntry, bool handled) REQUIRES(mLock); // Find touched state and touched window by token. |