Loading services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +10 −4 Original line number Original line Diff line number Diff line Loading @@ -55,12 +55,18 @@ private: ALOGE("There is no focused window for %s", applicationHandle->getName().c_str()); ALOGE("There is no focused window for %s", applicationHandle->getName().c_str()); } } void notifyConnectionUnresponsive(const sp<IBinder>& connectionToken, void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, const std::string& reason) override { const std::string& reason) override { ALOGE("Connection is not responding: %s", reason.c_str()); ALOGE("Window is not responding: %s", reason.c_str()); } } void notifyConnectionResponsive(const sp<IBinder>& connectionToken) override {} void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {} void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) override { ALOGE("Monitor is not responding: %s", reason.c_str()); } void notifyMonitorResponsive(int32_t pid) override {} void notifyInputChannelBroken(const sp<IBinder>&) override {} void notifyInputChannelBroken(const sp<IBinder>&) override {} Loading services/inputflinger/dispatcher/Entry.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -271,6 +271,7 @@ struct CommandEntry { sp<IBinder> newToken; sp<IBinder> newToken; std::string obscuringPackage; std::string obscuringPackage; bool enabled; bool enabled; int32_t pid; }; }; } // namespace android::inputdispatcher } // namespace android::inputdispatcher Loading services/inputflinger/dispatcher/InputDispatcher.cpp +133 −30 Original line number Original line Diff line number Diff line Loading @@ -453,6 +453,20 @@ static KeyEvent createKeyEvent(const KeyEntry& entry) { return event; return event; } } static std::optional<int32_t> findMonitorPidByToken( const std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay, const sp<IBinder>& token) { for (const auto& it : monitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; for (const Monitor& monitor : monitors) { if (monitor.inputChannel->getConnectionToken() == token) { return monitor.pid; } } } return std::nullopt; } // --- InputDispatcher --- // --- InputDispatcher --- InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) Loading Loading @@ -615,7 +629,7 @@ nsecs_t InputDispatcher::processAnrsLocked() { connection->responsive = false; connection->responsive = false; // Stop waking up for this unresponsive connection // Stop waking up for this unresponsive connection mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken()); mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken()); onAnrLocked(*connection); onAnrLocked(connection); return LONG_LONG_MIN; return LONG_LONG_MIN; } } Loading Loading @@ -5154,6 +5168,14 @@ std::optional<int32_t> InputDispatcher::findGestureMonitorDisplayByTokenLocked( return std::nullopt; return std::nullopt; } } std::optional<int32_t> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBinder>& token) { std::optional<int32_t> gesturePid = findMonitorPidByToken(mGestureMonitorsByDisplay, token); if (gesturePid.has_value()) { return gesturePid; } return findMonitorPidByToken(mGlobalMonitorsByDisplay, token); } sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const { sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const { if (inputConnectionToken == nullptr) { if (inputConnectionToken == nullptr) { return nullptr; return nullptr; Loading Loading @@ -5214,12 +5236,15 @@ void InputDispatcher::notifyFocusChangedLocked(const sp<IBinder>& oldToken, postCommandLocked(std::move(commandEntry)); postCommandLocked(std::move(commandEntry)); } } void InputDispatcher::onAnrLocked(const Connection& connection) { void InputDispatcher::onAnrLocked(const sp<Connection>& connection) { if (connection == nullptr) { LOG_ALWAYS_FATAL("Caller must check for nullness"); } // Since we are allowing the policy to extend the timeout, maybe the waitQueue // Since we are allowing the policy to extend the timeout, maybe the waitQueue // is already healthy again. Don't raise ANR in this situation // is already healthy again. Don't raise ANR in this situation if (connection.waitQueue.empty()) { if (connection->waitQueue.empty()) { ALOGI("Not raising ANR because the connection %s has recovered", ALOGI("Not raising ANR because the connection %s has recovered", connection.inputChannel->getName().c_str()); connection->inputChannel->getName().c_str()); return; return; } } /** /** Loading @@ -5230,21 +5255,20 @@ void InputDispatcher::onAnrLocked(const Connection& connection) { * processes the events linearly. So providing information about the oldest entry seems to be * processes the events linearly. So providing information about the oldest entry seems to be * most useful. * most useful. */ */ DispatchEntry* oldestEntry = *connection.waitQueue.begin(); DispatchEntry* oldestEntry = *connection->waitQueue.begin(); const nsecs_t currentWait = now() - oldestEntry->deliveryTime; const nsecs_t currentWait = now() - oldestEntry->deliveryTime; std::string reason = std::string reason = android::base::StringPrintf("%s is not responding. Waited %" PRId64 "ms for %s", android::base::StringPrintf("%s is not responding. Waited %" PRId64 "ms for %s", connection.inputChannel->getName().c_str(), connection->inputChannel->getName().c_str(), ns2ms(currentWait), ns2ms(currentWait), oldestEntry->eventEntry->getDescription().c_str()); oldestEntry->eventEntry->getDescription().c_str()); sp<IBinder> connectionToken = connection.inputChannel->getConnectionToken(); sp<IBinder> connectionToken = connection->inputChannel->getConnectionToken(); updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason); updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason); std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>( processConnectionUnresponsiveLocked(*connection, std::move(reason)); &InputDispatcher::doNotifyConnectionUnresponsiveLockedInterruptible); commandEntry->connectionToken = connectionToken; // Stop waking up for events on this connection, it is already unresponsive commandEntry->reason = std::move(reason); cancelEventsForAnrLocked(connection); postCommandLocked(std::move(commandEntry)); } } void InputDispatcher::onAnrLocked(std::shared_ptr<InputApplicationHandle> application) { void InputDispatcher::onAnrLocked(std::shared_ptr<InputApplicationHandle> application) { Loading Loading @@ -5329,26 +5353,34 @@ void InputDispatcher::doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry mLock.lock(); mLock.lock(); } } void InputDispatcher::doNotifyConnectionUnresponsiveLockedInterruptible( void InputDispatcher::doNotifyWindowUnresponsiveLockedInterruptible(CommandEntry* commandEntry) { CommandEntry* commandEntry) { mLock.unlock(); mLock.unlock(); mPolicy->notifyConnectionUnresponsive(commandEntry->connectionToken, commandEntry->reason); mPolicy->notifyWindowUnresponsive(commandEntry->connectionToken, commandEntry->reason); mLock.lock(); mLock.lock(); } // stop waking up for events in this connection, it is already not responding void InputDispatcher::doNotifyMonitorUnresponsiveLockedInterruptible(CommandEntry* commandEntry) { sp<Connection> connection = getConnectionLocked(commandEntry->connectionToken); mLock.unlock(); if (connection == nullptr) { return; mPolicy->notifyMonitorUnresponsive(commandEntry->pid, commandEntry->reason); mLock.lock(); } } cancelEventsForAnrLocked(connection); void InputDispatcher::doNotifyWindowResponsiveLockedInterruptible(CommandEntry* commandEntry) { mLock.unlock(); mPolicy->notifyWindowResponsive(commandEntry->connectionToken); mLock.lock(); } } void InputDispatcher::doNotifyConnectionResponsiveLockedInterruptible(CommandEntry* commandEntry) { void InputDispatcher::doNotifyMonitorResponsiveLockedInterruptible(CommandEntry* commandEntry) { mLock.unlock(); mLock.unlock(); mPolicy->notifyConnectionResponsive(commandEntry->connectionToken); mPolicy->notifyMonitorResponsive(commandEntry->pid); mLock.lock(); mLock.lock(); } } Loading Loading @@ -5453,13 +5485,8 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c if (!connection->responsive) { if (!connection->responsive) { connection->responsive = isConnectionResponsive(*connection); connection->responsive = isConnectionResponsive(*connection); if (connection->responsive) { if (connection->responsive) { // The connection was unresponsive, and now it's responsive. Tell the policy // The connection was unresponsive, and now it's responsive. // about it so that it can stop ANR. processConnectionResponsiveLocked(*connection); std::unique_ptr<CommandEntry> connectionResponsiveCommand = std::make_unique<CommandEntry>( &InputDispatcher::doNotifyConnectionResponsiveLockedInterruptible); connectionResponsiveCommand->connectionToken = connectionToken; postCommandLocked(std::move(connectionResponsiveCommand)); } } } } traceWaitQueueLength(connection); traceWaitQueueLength(connection); Loading @@ -5475,6 +5502,82 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c startDispatchCycleLocked(now(), connection); startDispatchCycleLocked(now(), connection); } } void InputDispatcher::sendMonitorUnresponsiveCommandLocked(int32_t pid, std::string reason) { std::unique_ptr<CommandEntry> monitorUnresponsiveCommand = std::make_unique<CommandEntry>( &InputDispatcher::doNotifyMonitorUnresponsiveLockedInterruptible); monitorUnresponsiveCommand->pid = pid; monitorUnresponsiveCommand->reason = std::move(reason); postCommandLocked(std::move(monitorUnresponsiveCommand)); } void InputDispatcher::sendWindowUnresponsiveCommandLocked(sp<IBinder> connectionToken, std::string reason) { std::unique_ptr<CommandEntry> windowUnresponsiveCommand = std::make_unique<CommandEntry>( &InputDispatcher::doNotifyWindowUnresponsiveLockedInterruptible); windowUnresponsiveCommand->connectionToken = std::move(connectionToken); windowUnresponsiveCommand->reason = std::move(reason); postCommandLocked(std::move(windowUnresponsiveCommand)); } void InputDispatcher::sendMonitorResponsiveCommandLocked(int32_t pid) { std::unique_ptr<CommandEntry> monitorResponsiveCommand = std::make_unique<CommandEntry>( &InputDispatcher::doNotifyMonitorResponsiveLockedInterruptible); monitorResponsiveCommand->pid = pid; postCommandLocked(std::move(monitorResponsiveCommand)); } void InputDispatcher::sendWindowResponsiveCommandLocked(sp<IBinder> connectionToken) { std::unique_ptr<CommandEntry> windowResponsiveCommand = std::make_unique<CommandEntry>( &InputDispatcher::doNotifyWindowResponsiveLockedInterruptible); windowResponsiveCommand->connectionToken = std::move(connectionToken); postCommandLocked(std::move(windowResponsiveCommand)); } /** * Tell the policy that a connection has become unresponsive so that it can start ANR. * Check whether the connection of interest is a monitor or a window, and add the corresponding * command entry to the command queue. */ void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& connection, std::string reason) { const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken(); if (connection.monitor) { ALOGW("Monitor %s is unresponsive: %s", connection.inputChannel->getName().c_str(), reason.c_str()); std::optional<int32_t> pid = findMonitorPidByTokenLocked(connectionToken); if (!pid.has_value()) { ALOGE("Could not find unresponsive monitor for connection %s", connection.inputChannel->getName().c_str()); return; } sendMonitorUnresponsiveCommandLocked(pid.value(), std::move(reason)); return; } // If not a monitor, must be a window ALOGW("Window %s is unresponsive: %s", connection.inputChannel->getName().c_str(), reason.c_str()); sendWindowUnresponsiveCommandLocked(connectionToken, std::move(reason)); } /** * Tell the policy that a connection has become responsive so that it can stop ANR. */ void InputDispatcher::processConnectionResponsiveLocked(const Connection& connection) { const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken(); if (connection.monitor) { std::optional<int32_t> pid = findMonitorPidByTokenLocked(connectionToken); if (!pid.has_value()) { ALOGE("Could not find responsive monitor for connection %s", connection.inputChannel->getName().c_str()); return; } sendMonitorResponsiveCommandLocked(pid.value()); return; } // If not a monitor, must be a window sendWindowResponsiveCommandLocked(connectionToken); } bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection, bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection, DispatchEntry* dispatchEntry, DispatchEntry* dispatchEntry, KeyEntry& keyEntry, bool handled) { KeyEntry& keyEntry, bool handled) { Loading services/inputflinger/dispatcher/InputDispatcher.h +37 −5 Original line number Original line Diff line number Diff line Loading @@ -233,6 +233,8 @@ private: // Finds the display ID of the gesture monitor identified by the provided token. // Finds the display ID of the gesture monitor identified by the provided token. std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token) std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock); REQUIRES(mLock); // Find a monitor pid by the provided token. std::optional<int32_t> findMonitorPidByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock); // Input channels that will receive a copy of all input events sent to the provided display. // Input channels that will receive a copy of all input events sent to the provided display. std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay GUARDED_BY(mLock); std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay GUARDED_BY(mLock); Loading Loading @@ -432,6 +434,34 @@ private: int32_t mAwaitedApplicationDisplayId GUARDED_BY(mLock); int32_t mAwaitedApplicationDisplayId GUARDED_BY(mLock); void processNoFocusedWindowAnrLocked() REQUIRES(mLock); void processNoFocusedWindowAnrLocked() REQUIRES(mLock); /** * Tell policy about a window or a monitor that just became unresponsive. Starts ANR. */ void processConnectionUnresponsiveLocked(const Connection& connection, std::string reason) REQUIRES(mLock); /** * Tell policy about a window or a monitor that just became responsive. */ void processConnectionResponsiveLocked(const Connection& connection) REQUIRES(mLock); /** * Post `doNotifyMonitorUnresponsiveLockedInterruptible` command. */ void sendMonitorUnresponsiveCommandLocked(int32_t pid, std::string reason) REQUIRES(mLock); /** * Post `doNotifyWindowUnresponsiveLockedInterruptible` command. */ void sendWindowUnresponsiveCommandLocked(sp<IBinder> connectionToken, std::string reason) REQUIRES(mLock); /** * Post `doNotifyMonitorResponsiveLockedInterruptible` command. */ void sendMonitorResponsiveCommandLocked(int32_t pid) REQUIRES(mLock); /** * Post `doNotifyWindowResponsiveLockedInterruptible` command. */ void sendWindowResponsiveCommandLocked(sp<IBinder> connectionToken) REQUIRES(mLock); /** /** * This map will store the pending focus requests that cannot be currently processed. This can * This map will store the pending focus requests that cannot be currently processed. This can * happen if the window requested to be focused is not currently visible. Such a window might * happen if the window requested to be focused is not currently visible. Such a window might Loading Loading @@ -577,7 +607,7 @@ private: int32_t displayId, std::string_view reason) REQUIRES(mLock); int32_t displayId, std::string_view reason) REQUIRES(mLock); void notifyFocusChangedLocked(const sp<IBinder>& oldFocus, const sp<IBinder>& newFocus) void notifyFocusChangedLocked(const sp<IBinder>& oldFocus, const sp<IBinder>& newFocus) REQUIRES(mLock); REQUIRES(mLock); void onAnrLocked(const Connection& connection) REQUIRES(mLock); void onAnrLocked(const sp<Connection>& connection) REQUIRES(mLock); void onAnrLocked(std::shared_ptr<InputApplicationHandle> application) REQUIRES(mLock); void onAnrLocked(std::shared_ptr<InputApplicationHandle> application) REQUIRES(mLock); void onUntrustedTouchLocked(const std::string& obscuringPackage) REQUIRES(mLock); void onUntrustedTouchLocked(const std::string& obscuringPackage) REQUIRES(mLock); void updateLastAnrStateLocked(const sp<InputWindowHandle>& window, const std::string& reason) void updateLastAnrStateLocked(const sp<InputWindowHandle>& window, const std::string& reason) Loading @@ -592,11 +622,13 @@ private: REQUIRES(mLock); REQUIRES(mLock); void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); // ANR-related callbacks - start void doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyConnectionUnresponsiveLockedInterruptible(CommandEntry* commandEntry) void doNotifyWindowUnresponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); REQUIRES(mLock); void doNotifyMonitorUnresponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyConnectionResponsiveLockedInterruptible(CommandEntry* commandEntry) void doNotifyWindowResponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); REQUIRES(mLock); void doNotifyMonitorResponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); // ANR-related callbacks - end void doNotifySensorLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifySensorLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyUntrustedTouchLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyUntrustedTouchLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry) void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry) Loading services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +19 −8 Original line number Original line Diff line number Diff line Loading @@ -50,20 +50,31 @@ public: virtual void notifyNoFocusedWindowAnr( virtual void notifyNoFocusedWindowAnr( const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) = 0; const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) = 0; /* Notifies the system that a connection just became unresponsive. This indicates that ANR /* Notifies the system that a window just became unresponsive. This indicates that ANR * should be raised for this connection. The connection is identified via token. * should be raised for this window. The window is identified via token. * The string reason contains information about the input event that we haven't received * The string reason contains information about the input event that we haven't received * a response for. * a response for. */ */ virtual void notifyConnectionUnresponsive(const sp<IBinder>& token, virtual void notifyWindowUnresponsive(const sp<IBinder>& token, const std::string& reason) = 0; const std::string& reason) = 0; /* Notifies the system that a monitor just became unresponsive. This indicates that ANR * should be raised for this monitor. The monitor is identified via its pid. * The string reason contains information about the input event that we haven't received * a response for. */ virtual void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) = 0; /* Notifies the system that a connection just became responsive. This is only called after the /* Notifies the system that a window just became responsive. This is only called after the * connection was first marked "unresponsive". This indicates that ANR dialog (if any) should * window was first marked "unresponsive". This indicates that ANR dialog (if any) should * no longer should be shown to the user. The connection is eligible to cause a new ANR in the * no longer should be shown to the user. The window is eligible to cause a new ANR in the * future. */ virtual void notifyWindowResponsive(const sp<IBinder>& token) = 0; /* Notifies the system that a monitor just became responsive. This is only called after the * monitor was first marked "unresponsive". This indicates that ANR dialog (if any) should * no longer should be shown to the user. The monitor is eligible to cause a new ANR in the * future. * future. */ */ virtual void notifyConnectionResponsive(const sp<IBinder>& token) = 0; virtual void notifyMonitorResponsive(int32_t pid) = 0; /* Notifies the system that an input channel is unrecoverably broken. */ /* Notifies the system that an input channel is unrecoverably broken. */ virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0; virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0; Loading Loading
services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +10 −4 Original line number Original line Diff line number Diff line Loading @@ -55,12 +55,18 @@ private: ALOGE("There is no focused window for %s", applicationHandle->getName().c_str()); ALOGE("There is no focused window for %s", applicationHandle->getName().c_str()); } } void notifyConnectionUnresponsive(const sp<IBinder>& connectionToken, void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, const std::string& reason) override { const std::string& reason) override { ALOGE("Connection is not responding: %s", reason.c_str()); ALOGE("Window is not responding: %s", reason.c_str()); } } void notifyConnectionResponsive(const sp<IBinder>& connectionToken) override {} void notifyWindowResponsive(const sp<IBinder>& connectionToken) override {} void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) override { ALOGE("Monitor is not responding: %s", reason.c_str()); } void notifyMonitorResponsive(int32_t pid) override {} void notifyInputChannelBroken(const sp<IBinder>&) override {} void notifyInputChannelBroken(const sp<IBinder>&) override {} Loading
services/inputflinger/dispatcher/Entry.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -271,6 +271,7 @@ struct CommandEntry { sp<IBinder> newToken; sp<IBinder> newToken; std::string obscuringPackage; std::string obscuringPackage; bool enabled; bool enabled; int32_t pid; }; }; } // namespace android::inputdispatcher } // namespace android::inputdispatcher Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +133 −30 Original line number Original line Diff line number Diff line Loading @@ -453,6 +453,20 @@ static KeyEvent createKeyEvent(const KeyEntry& entry) { return event; return event; } } static std::optional<int32_t> findMonitorPidByToken( const std::unordered_map<int32_t, std::vector<Monitor>>& monitorsByDisplay, const sp<IBinder>& token) { for (const auto& it : monitorsByDisplay) { const std::vector<Monitor>& monitors = it.second; for (const Monitor& monitor : monitors) { if (monitor.inputChannel->getConnectionToken() == token) { return monitor.pid; } } } return std::nullopt; } // --- InputDispatcher --- // --- InputDispatcher --- InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) Loading Loading @@ -615,7 +629,7 @@ nsecs_t InputDispatcher::processAnrsLocked() { connection->responsive = false; connection->responsive = false; // Stop waking up for this unresponsive connection // Stop waking up for this unresponsive connection mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken()); mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken()); onAnrLocked(*connection); onAnrLocked(connection); return LONG_LONG_MIN; return LONG_LONG_MIN; } } Loading Loading @@ -5154,6 +5168,14 @@ std::optional<int32_t> InputDispatcher::findGestureMonitorDisplayByTokenLocked( return std::nullopt; return std::nullopt; } } std::optional<int32_t> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBinder>& token) { std::optional<int32_t> gesturePid = findMonitorPidByToken(mGestureMonitorsByDisplay, token); if (gesturePid.has_value()) { return gesturePid; } return findMonitorPidByToken(mGlobalMonitorsByDisplay, token); } sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const { sp<Connection> InputDispatcher::getConnectionLocked(const sp<IBinder>& inputConnectionToken) const { if (inputConnectionToken == nullptr) { if (inputConnectionToken == nullptr) { return nullptr; return nullptr; Loading Loading @@ -5214,12 +5236,15 @@ void InputDispatcher::notifyFocusChangedLocked(const sp<IBinder>& oldToken, postCommandLocked(std::move(commandEntry)); postCommandLocked(std::move(commandEntry)); } } void InputDispatcher::onAnrLocked(const Connection& connection) { void InputDispatcher::onAnrLocked(const sp<Connection>& connection) { if (connection == nullptr) { LOG_ALWAYS_FATAL("Caller must check for nullness"); } // Since we are allowing the policy to extend the timeout, maybe the waitQueue // Since we are allowing the policy to extend the timeout, maybe the waitQueue // is already healthy again. Don't raise ANR in this situation // is already healthy again. Don't raise ANR in this situation if (connection.waitQueue.empty()) { if (connection->waitQueue.empty()) { ALOGI("Not raising ANR because the connection %s has recovered", ALOGI("Not raising ANR because the connection %s has recovered", connection.inputChannel->getName().c_str()); connection->inputChannel->getName().c_str()); return; return; } } /** /** Loading @@ -5230,21 +5255,20 @@ void InputDispatcher::onAnrLocked(const Connection& connection) { * processes the events linearly. So providing information about the oldest entry seems to be * processes the events linearly. So providing information about the oldest entry seems to be * most useful. * most useful. */ */ DispatchEntry* oldestEntry = *connection.waitQueue.begin(); DispatchEntry* oldestEntry = *connection->waitQueue.begin(); const nsecs_t currentWait = now() - oldestEntry->deliveryTime; const nsecs_t currentWait = now() - oldestEntry->deliveryTime; std::string reason = std::string reason = android::base::StringPrintf("%s is not responding. Waited %" PRId64 "ms for %s", android::base::StringPrintf("%s is not responding. Waited %" PRId64 "ms for %s", connection.inputChannel->getName().c_str(), connection->inputChannel->getName().c_str(), ns2ms(currentWait), ns2ms(currentWait), oldestEntry->eventEntry->getDescription().c_str()); oldestEntry->eventEntry->getDescription().c_str()); sp<IBinder> connectionToken = connection.inputChannel->getConnectionToken(); sp<IBinder> connectionToken = connection->inputChannel->getConnectionToken(); updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason); updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason); std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>( processConnectionUnresponsiveLocked(*connection, std::move(reason)); &InputDispatcher::doNotifyConnectionUnresponsiveLockedInterruptible); commandEntry->connectionToken = connectionToken; // Stop waking up for events on this connection, it is already unresponsive commandEntry->reason = std::move(reason); cancelEventsForAnrLocked(connection); postCommandLocked(std::move(commandEntry)); } } void InputDispatcher::onAnrLocked(std::shared_ptr<InputApplicationHandle> application) { void InputDispatcher::onAnrLocked(std::shared_ptr<InputApplicationHandle> application) { Loading Loading @@ -5329,26 +5353,34 @@ void InputDispatcher::doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry mLock.lock(); mLock.lock(); } } void InputDispatcher::doNotifyConnectionUnresponsiveLockedInterruptible( void InputDispatcher::doNotifyWindowUnresponsiveLockedInterruptible(CommandEntry* commandEntry) { CommandEntry* commandEntry) { mLock.unlock(); mLock.unlock(); mPolicy->notifyConnectionUnresponsive(commandEntry->connectionToken, commandEntry->reason); mPolicy->notifyWindowUnresponsive(commandEntry->connectionToken, commandEntry->reason); mLock.lock(); mLock.lock(); } // stop waking up for events in this connection, it is already not responding void InputDispatcher::doNotifyMonitorUnresponsiveLockedInterruptible(CommandEntry* commandEntry) { sp<Connection> connection = getConnectionLocked(commandEntry->connectionToken); mLock.unlock(); if (connection == nullptr) { return; mPolicy->notifyMonitorUnresponsive(commandEntry->pid, commandEntry->reason); mLock.lock(); } } cancelEventsForAnrLocked(connection); void InputDispatcher::doNotifyWindowResponsiveLockedInterruptible(CommandEntry* commandEntry) { mLock.unlock(); mPolicy->notifyWindowResponsive(commandEntry->connectionToken); mLock.lock(); } } void InputDispatcher::doNotifyConnectionResponsiveLockedInterruptible(CommandEntry* commandEntry) { void InputDispatcher::doNotifyMonitorResponsiveLockedInterruptible(CommandEntry* commandEntry) { mLock.unlock(); mLock.unlock(); mPolicy->notifyConnectionResponsive(commandEntry->connectionToken); mPolicy->notifyMonitorResponsive(commandEntry->pid); mLock.lock(); mLock.lock(); } } Loading Loading @@ -5453,13 +5485,8 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c if (!connection->responsive) { if (!connection->responsive) { connection->responsive = isConnectionResponsive(*connection); connection->responsive = isConnectionResponsive(*connection); if (connection->responsive) { if (connection->responsive) { // The connection was unresponsive, and now it's responsive. Tell the policy // The connection was unresponsive, and now it's responsive. // about it so that it can stop ANR. processConnectionResponsiveLocked(*connection); std::unique_ptr<CommandEntry> connectionResponsiveCommand = std::make_unique<CommandEntry>( &InputDispatcher::doNotifyConnectionResponsiveLockedInterruptible); connectionResponsiveCommand->connectionToken = connectionToken; postCommandLocked(std::move(connectionResponsiveCommand)); } } } } traceWaitQueueLength(connection); traceWaitQueueLength(connection); Loading @@ -5475,6 +5502,82 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* c startDispatchCycleLocked(now(), connection); startDispatchCycleLocked(now(), connection); } } void InputDispatcher::sendMonitorUnresponsiveCommandLocked(int32_t pid, std::string reason) { std::unique_ptr<CommandEntry> monitorUnresponsiveCommand = std::make_unique<CommandEntry>( &InputDispatcher::doNotifyMonitorUnresponsiveLockedInterruptible); monitorUnresponsiveCommand->pid = pid; monitorUnresponsiveCommand->reason = std::move(reason); postCommandLocked(std::move(monitorUnresponsiveCommand)); } void InputDispatcher::sendWindowUnresponsiveCommandLocked(sp<IBinder> connectionToken, std::string reason) { std::unique_ptr<CommandEntry> windowUnresponsiveCommand = std::make_unique<CommandEntry>( &InputDispatcher::doNotifyWindowUnresponsiveLockedInterruptible); windowUnresponsiveCommand->connectionToken = std::move(connectionToken); windowUnresponsiveCommand->reason = std::move(reason); postCommandLocked(std::move(windowUnresponsiveCommand)); } void InputDispatcher::sendMonitorResponsiveCommandLocked(int32_t pid) { std::unique_ptr<CommandEntry> monitorResponsiveCommand = std::make_unique<CommandEntry>( &InputDispatcher::doNotifyMonitorResponsiveLockedInterruptible); monitorResponsiveCommand->pid = pid; postCommandLocked(std::move(monitorResponsiveCommand)); } void InputDispatcher::sendWindowResponsiveCommandLocked(sp<IBinder> connectionToken) { std::unique_ptr<CommandEntry> windowResponsiveCommand = std::make_unique<CommandEntry>( &InputDispatcher::doNotifyWindowResponsiveLockedInterruptible); windowResponsiveCommand->connectionToken = std::move(connectionToken); postCommandLocked(std::move(windowResponsiveCommand)); } /** * Tell the policy that a connection has become unresponsive so that it can start ANR. * Check whether the connection of interest is a monitor or a window, and add the corresponding * command entry to the command queue. */ void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& connection, std::string reason) { const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken(); if (connection.monitor) { ALOGW("Monitor %s is unresponsive: %s", connection.inputChannel->getName().c_str(), reason.c_str()); std::optional<int32_t> pid = findMonitorPidByTokenLocked(connectionToken); if (!pid.has_value()) { ALOGE("Could not find unresponsive monitor for connection %s", connection.inputChannel->getName().c_str()); return; } sendMonitorUnresponsiveCommandLocked(pid.value(), std::move(reason)); return; } // If not a monitor, must be a window ALOGW("Window %s is unresponsive: %s", connection.inputChannel->getName().c_str(), reason.c_str()); sendWindowUnresponsiveCommandLocked(connectionToken, std::move(reason)); } /** * Tell the policy that a connection has become responsive so that it can stop ANR. */ void InputDispatcher::processConnectionResponsiveLocked(const Connection& connection) { const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken(); if (connection.monitor) { std::optional<int32_t> pid = findMonitorPidByTokenLocked(connectionToken); if (!pid.has_value()) { ALOGE("Could not find responsive monitor for connection %s", connection.inputChannel->getName().c_str()); return; } sendMonitorResponsiveCommandLocked(pid.value()); return; } // If not a monitor, must be a window sendWindowResponsiveCommandLocked(connectionToken); } bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection, bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection, DispatchEntry* dispatchEntry, DispatchEntry* dispatchEntry, KeyEntry& keyEntry, bool handled) { KeyEntry& keyEntry, bool handled) { Loading
services/inputflinger/dispatcher/InputDispatcher.h +37 −5 Original line number Original line Diff line number Diff line Loading @@ -233,6 +233,8 @@ private: // Finds the display ID of the gesture monitor identified by the provided token. // Finds the display ID of the gesture monitor identified by the provided token. std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token) std::optional<int32_t> findGestureMonitorDisplayByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock); REQUIRES(mLock); // Find a monitor pid by the provided token. std::optional<int32_t> findMonitorPidByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock); // Input channels that will receive a copy of all input events sent to the provided display. // Input channels that will receive a copy of all input events sent to the provided display. std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay GUARDED_BY(mLock); std::unordered_map<int32_t, std::vector<Monitor>> mGlobalMonitorsByDisplay GUARDED_BY(mLock); Loading Loading @@ -432,6 +434,34 @@ private: int32_t mAwaitedApplicationDisplayId GUARDED_BY(mLock); int32_t mAwaitedApplicationDisplayId GUARDED_BY(mLock); void processNoFocusedWindowAnrLocked() REQUIRES(mLock); void processNoFocusedWindowAnrLocked() REQUIRES(mLock); /** * Tell policy about a window or a monitor that just became unresponsive. Starts ANR. */ void processConnectionUnresponsiveLocked(const Connection& connection, std::string reason) REQUIRES(mLock); /** * Tell policy about a window or a monitor that just became responsive. */ void processConnectionResponsiveLocked(const Connection& connection) REQUIRES(mLock); /** * Post `doNotifyMonitorUnresponsiveLockedInterruptible` command. */ void sendMonitorUnresponsiveCommandLocked(int32_t pid, std::string reason) REQUIRES(mLock); /** * Post `doNotifyWindowUnresponsiveLockedInterruptible` command. */ void sendWindowUnresponsiveCommandLocked(sp<IBinder> connectionToken, std::string reason) REQUIRES(mLock); /** * Post `doNotifyMonitorResponsiveLockedInterruptible` command. */ void sendMonitorResponsiveCommandLocked(int32_t pid) REQUIRES(mLock); /** * Post `doNotifyWindowResponsiveLockedInterruptible` command. */ void sendWindowResponsiveCommandLocked(sp<IBinder> connectionToken) REQUIRES(mLock); /** /** * This map will store the pending focus requests that cannot be currently processed. This can * This map will store the pending focus requests that cannot be currently processed. This can * happen if the window requested to be focused is not currently visible. Such a window might * happen if the window requested to be focused is not currently visible. Such a window might Loading Loading @@ -577,7 +607,7 @@ private: int32_t displayId, std::string_view reason) REQUIRES(mLock); int32_t displayId, std::string_view reason) REQUIRES(mLock); void notifyFocusChangedLocked(const sp<IBinder>& oldFocus, const sp<IBinder>& newFocus) void notifyFocusChangedLocked(const sp<IBinder>& oldFocus, const sp<IBinder>& newFocus) REQUIRES(mLock); REQUIRES(mLock); void onAnrLocked(const Connection& connection) REQUIRES(mLock); void onAnrLocked(const sp<Connection>& connection) REQUIRES(mLock); void onAnrLocked(std::shared_ptr<InputApplicationHandle> application) REQUIRES(mLock); void onAnrLocked(std::shared_ptr<InputApplicationHandle> application) REQUIRES(mLock); void onUntrustedTouchLocked(const std::string& obscuringPackage) REQUIRES(mLock); void onUntrustedTouchLocked(const std::string& obscuringPackage) REQUIRES(mLock); void updateLastAnrStateLocked(const sp<InputWindowHandle>& window, const std::string& reason) void updateLastAnrStateLocked(const sp<InputWindowHandle>& window, const std::string& reason) Loading @@ -592,11 +622,13 @@ private: REQUIRES(mLock); REQUIRES(mLock); void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); // ANR-related callbacks - start void doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyConnectionUnresponsiveLockedInterruptible(CommandEntry* commandEntry) void doNotifyWindowUnresponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); REQUIRES(mLock); void doNotifyMonitorUnresponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyConnectionResponsiveLockedInterruptible(CommandEntry* commandEntry) void doNotifyWindowResponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); REQUIRES(mLock); void doNotifyMonitorResponsiveLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); // ANR-related callbacks - end void doNotifySensorLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifySensorLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyUntrustedTouchLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyUntrustedTouchLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry) void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry) Loading
services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +19 −8 Original line number Original line Diff line number Diff line Loading @@ -50,20 +50,31 @@ public: virtual void notifyNoFocusedWindowAnr( virtual void notifyNoFocusedWindowAnr( const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) = 0; const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) = 0; /* Notifies the system that a connection just became unresponsive. This indicates that ANR /* Notifies the system that a window just became unresponsive. This indicates that ANR * should be raised for this connection. The connection is identified via token. * should be raised for this window. The window is identified via token. * The string reason contains information about the input event that we haven't received * The string reason contains information about the input event that we haven't received * a response for. * a response for. */ */ virtual void notifyConnectionUnresponsive(const sp<IBinder>& token, virtual void notifyWindowUnresponsive(const sp<IBinder>& token, const std::string& reason) = 0; const std::string& reason) = 0; /* Notifies the system that a monitor just became unresponsive. This indicates that ANR * should be raised for this monitor. The monitor is identified via its pid. * The string reason contains information about the input event that we haven't received * a response for. */ virtual void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) = 0; /* Notifies the system that a connection just became responsive. This is only called after the /* Notifies the system that a window just became responsive. This is only called after the * connection was first marked "unresponsive". This indicates that ANR dialog (if any) should * window was first marked "unresponsive". This indicates that ANR dialog (if any) should * no longer should be shown to the user. The connection is eligible to cause a new ANR in the * no longer should be shown to the user. The window is eligible to cause a new ANR in the * future. */ virtual void notifyWindowResponsive(const sp<IBinder>& token) = 0; /* Notifies the system that a monitor just became responsive. This is only called after the * monitor was first marked "unresponsive". This indicates that ANR dialog (if any) should * no longer should be shown to the user. The monitor is eligible to cause a new ANR in the * future. * future. */ */ virtual void notifyConnectionResponsive(const sp<IBinder>& token) = 0; virtual void notifyMonitorResponsive(int32_t pid) = 0; /* Notifies the system that an input channel is unrecoverably broken. */ /* Notifies the system that an input channel is unrecoverably broken. */ virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0; virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0; Loading