Tell policy about responsive connections

If a connection is unresponsive, we tell the policy about it. Now, with
this patch, we will also tell the policy that a connection becomes
responsive again. This will allow the policy to cancel the ANR dialog if
it's currently shown, and to stop recurring ANR dialogs if the user was
previously waiting for the app longer.

Bug: 171218828
Test: atest inputflinger_tests
Test: manual test via unresponsive apps
Change-Id: Ifc00601b2c4e44b721a30d5f9ebf786780d1ffd7
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index d6fa74d..bb27469 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2335,7 +2335,7 @@
 }
 
 std::string InputDispatcher::getApplicationWindowLabel(
-        const std::shared_ptr<InputApplicationHandle>& applicationHandle,
+        const InputApplicationHandle* applicationHandle,
         const sp<InputWindowHandle>& windowHandle) {
     if (applicationHandle != nullptr) {
         if (windowHandle != nullptr) {
@@ -4921,24 +4921,21 @@
     sp<IBinder> connectionToken = connection.inputChannel->getConnectionToken();
     updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason);
 
-    std::unique_ptr<CommandEntry> commandEntry =
-            std::make_unique<CommandEntry>(&InputDispatcher::doNotifyAnrLockedInterruptible);
-    commandEntry->inputApplicationHandle = nullptr;
+    std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
+            &InputDispatcher::doNotifyConnectionUnresponsiveLockedInterruptible);
     commandEntry->connectionToken = connectionToken;
     commandEntry->reason = std::move(reason);
     postCommandLocked(std::move(commandEntry));
 }
 
-void InputDispatcher::onAnrLocked(const std::shared_ptr<InputApplicationHandle>& application) {
-    std::string reason = android::base::StringPrintf("%s does not have a focused window",
-                                                     application->getName().c_str());
+void InputDispatcher::onAnrLocked(std::shared_ptr<InputApplicationHandle> application) {
+    std::string reason =
+            StringPrintf("%s does not have a focused window", application->getName().c_str());
+    updateLastAnrStateLocked(*application, reason);
 
-    updateLastAnrStateLocked(application, reason);
-
-    std::unique_ptr<CommandEntry> commandEntry =
-            std::make_unique<CommandEntry>(&InputDispatcher::doNotifyAnrLockedInterruptible);
-    commandEntry->inputApplicationHandle = application;
-    commandEntry->reason = std::move(reason);
+    std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
+            &InputDispatcher::doNotifyNoFocusedWindowAnrLockedInterruptible);
+    commandEntry->inputApplicationHandle = std::move(application);
     postCommandLocked(std::move(commandEntry));
 }
 
@@ -4955,9 +4952,9 @@
     updateLastAnrStateLocked(windowLabel, reason);
 }
 
-void InputDispatcher::updateLastAnrStateLocked(
-        const std::shared_ptr<InputApplicationHandle>& application, const std::string& reason) {
-    const std::string windowLabel = getApplicationWindowLabel(application, nullptr);
+void InputDispatcher::updateLastAnrStateLocked(const InputApplicationHandle& application,
+                                               const std::string& reason) {
+    const std::string windowLabel = getApplicationWindowLabel(&application, nullptr);
     updateLastAnrStateLocked(windowLabel, reason);
 }
 
@@ -5005,24 +5002,36 @@
     mLock.lock();
 }
 
-void InputDispatcher::doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) {
+void InputDispatcher::doNotifyNoFocusedWindowAnrLockedInterruptible(CommandEntry* commandEntry) {
     mLock.unlock();
-    const sp<IBinder>& token = commandEntry->connectionToken;
-    const std::chrono::nanoseconds timeoutExtension =
-            mPolicy->notifyAnr(commandEntry->inputApplicationHandle, token, commandEntry->reason);
+
+    mPolicy->notifyNoFocusedWindowAnr(commandEntry->inputApplicationHandle);
+
+    mLock.lock();
+}
+
+void InputDispatcher::doNotifyConnectionUnresponsiveLockedInterruptible(
+        CommandEntry* commandEntry) {
+    mLock.unlock();
+
+    mPolicy->notifyConnectionUnresponsive(commandEntry->connectionToken, commandEntry->reason);
 
     mLock.lock();
 
-    if (timeoutExtension > 0s) {
-        extendAnrTimeoutsLocked(commandEntry->inputApplicationHandle, token, timeoutExtension);
-    } else {
-        // stop waking up for events in this connection, it is already not responding
-        sp<Connection> connection = getConnectionLocked(token);
-        if (connection == nullptr) {
-            return;
-        }
-        cancelEventsForAnrLocked(connection);
+    // stop waking up for events in this connection, it is already not responding
+    sp<Connection> connection = getConnectionLocked(commandEntry->connectionToken);
+    if (connection == nullptr) {
+        return;
     }
+    cancelEventsForAnrLocked(connection);
+}
+
+void InputDispatcher::doNotifyConnectionResponsiveLockedInterruptible(CommandEntry* commandEntry) {
+    mLock.unlock();
+
+    mPolicy->notifyConnectionResponsive(commandEntry->connectionToken);
+
+    mLock.lock();
 }
 
 void InputDispatcher::doNotifyUntrustedTouchLockedInterruptible(CommandEntry* commandEntry) {
@@ -5033,35 +5042,6 @@
     mLock.lock();
 }
 
-void InputDispatcher::extendAnrTimeoutsLocked(
-        const std::shared_ptr<InputApplicationHandle>& application,
-        const sp<IBinder>& connectionToken, std::chrono::nanoseconds timeoutExtension) {
-    if (connectionToken == nullptr && application != nullptr) {
-        // The ANR happened because there's no focused window
-        mNoFocusedWindowTimeoutTime = now() + timeoutExtension.count();
-        mAwaitedFocusedApplication = application;
-    }
-
-    sp<Connection> connection = getConnectionLocked(connectionToken);
-    if (connection == nullptr) {
-        // It's possible that the connection already disappeared. No action necessary.
-        return;
-    }
-
-    ALOGI("Raised ANR, but the policy wants to keep waiting on %s for %" PRId64 "ms longer",
-          connection->inputChannel->getName().c_str(), millis(timeoutExtension));
-
-    connection->responsive = true;
-    const nsecs_t newTimeout = now() + timeoutExtension.count();
-    for (DispatchEntry* entry : connection->waitQueue) {
-        if (newTimeout >= entry->timeoutTime) {
-            // Already removed old entries when connection was marked unresponsive
-            entry->timeoutTime = newTimeout;
-            mAnrTracker.insert(entry->timeoutTime, connectionToken);
-        }
-    }
-}
-
 void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
         CommandEntry* commandEntry) {
     KeyEntry& entry = *(commandEntry->keyEntry);
@@ -5149,10 +5129,19 @@
     if (dispatchEntryIt != connection->waitQueue.end()) {
         dispatchEntry = *dispatchEntryIt;
         connection->waitQueue.erase(dispatchEntryIt);
-        mAnrTracker.erase(dispatchEntry->timeoutTime,
-                          connection->inputChannel->getConnectionToken());
+        const sp<IBinder>& connectionToken = connection->inputChannel->getConnectionToken();
+        mAnrTracker.erase(dispatchEntry->timeoutTime, connectionToken);
         if (!connection->responsive) {
             connection->responsive = isConnectionResponsive(*connection);
+            if (connection->responsive) {
+                // The connection was unresponsive, and now it's responsive. Tell the policy
+                // about it so that it can stop ANR.
+                std::unique_ptr<CommandEntry> connectionResponsiveCommand =
+                        std::make_unique<CommandEntry>(
+                                &InputDispatcher::doNotifyConnectionResponsiveLockedInterruptible);
+                connectionResponsiveCommand->connectionToken = connectionToken;
+                postCommandLocked(std::move(connectionResponsiveCommand));
+            }
         }
         traceWaitQueueLength(connection);
         if (restartEvent && connection->status == Connection::STATUS_NORMAL) {