InputDispatcher: Blame the window from the focus request for ANR

If there are no focusable windows, then try to blame the window that
was requested to become focused. This will avoid blaming the wrong
process when WM requests focus on a window that is placed on top
of the focused app and the window fails to become focusable.

Test: atest inputflinger_tests
Fixes: b/239907039

Change-Id: Ie2bc3dc66516b51784159a875c7cf865b4cb5b35
diff --git a/services/inputflinger/dispatcher/FocusResolver.cpp b/services/inputflinger/dispatcher/FocusResolver.cpp
index 4da846b..85dcf8f 100644
--- a/services/inputflinger/dispatcher/FocusResolver.cpp
+++ b/services/inputflinger/dispatcher/FocusResolver.cpp
@@ -39,7 +39,7 @@
     return it != mFocusedWindowTokenByDisplay.end() ? it->second.second : nullptr;
 }
 
-std::optional<FocusRequest> FocusResolver::getFocusRequest(int32_t displayId) {
+std::optional<FocusRequest> FocusResolver::getFocusRequest(int32_t displayId) const {
     auto it = mFocusRequestByDisplay.find(displayId);
     return it != mFocusRequestByDisplay.end() ? std::make_optional<>(it->second) : std::nullopt;
 }
diff --git a/services/inputflinger/dispatcher/FocusResolver.h b/services/inputflinger/dispatcher/FocusResolver.h
index 6d11a77..8a6dfa4 100644
--- a/services/inputflinger/dispatcher/FocusResolver.h
+++ b/services/inputflinger/dispatcher/FocusResolver.h
@@ -62,6 +62,7 @@
     std::optional<FocusResolver::FocusChanges> setFocusedWindow(
             const android::gui::FocusRequest& request,
             const std::vector<sp<android::gui::WindowInfoHandle>>& windows);
+    std::optional<android::gui::FocusRequest> getFocusRequest(int32_t displayId) const;
 
     // Display has been removed from the system, clean up old references.
     void displayRemoved(int32_t displayId);
@@ -112,7 +113,6 @@
     std::optional<FocusResolver::FocusChanges> updateFocusedWindow(
             int32_t displayId, const std::string& reason, const sp<IBinder>& token,
             const std::string& tokenName = "");
-    std::optional<android::gui::FocusRequest> getFocusRequest(int32_t displayId);
 };
 
 } // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index ff63967..b52e312 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -659,6 +659,13 @@
     if (focusedWindowHandle != nullptr) {
         return; // We now have a focused window. No need for ANR.
     }
+    std::optional<FocusRequest> pendingRequest =
+            mFocusResolver.getFocusRequest(mAwaitedApplicationDisplayId);
+    if (pendingRequest.has_value() && onAnrLocked(*pendingRequest)) {
+        // We don't have a focusable window but we know which window should have
+        // been focused. Blame that process in case it doesn't belong to the focused app.
+        return;
+    }
     onAnrLocked(mAwaitedFocusedApplication);
 }
 
@@ -5848,6 +5855,25 @@
     postCommandLocked(std::move(command));
 }
 
+bool InputDispatcher::onAnrLocked(const android::gui::FocusRequest& pendingFocusRequest) {
+    if (pendingFocusRequest.token == nullptr) {
+        return false;
+    }
+
+    const std::string reason = android::base::StringPrintf("%s is not focusable.",
+                                                           pendingFocusRequest.windowName.c_str());
+    updateLastAnrStateLocked(pendingFocusRequest.windowName, reason);
+    sp<Connection> connection = getConnectionLocked(pendingFocusRequest.token);
+    if (connection != nullptr) {
+        processConnectionUnresponsiveLocked(*connection, std::move(reason));
+        // Stop waking up for events on this connection, it is already unresponsive
+        cancelEventsForAnrLocked(connection);
+    } else {
+        sendWindowUnresponsiveCommandLocked(pendingFocusRequest.token, std::nullopt, reason);
+    }
+    return true;
+}
+
 void InputDispatcher::onAnrLocked(const sp<Connection>& connection) {
     if (connection == nullptr) {
         LOG_ALWAYS_FATAL("Caller must check for nullness");
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index be619ae..dc6dd5c 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -658,6 +658,7 @@
     void sendDropWindowCommandLocked(const sp<IBinder>& token, float x, float y) REQUIRES(mLock);
     void onAnrLocked(const sp<Connection>& connection) REQUIRES(mLock);
     void onAnrLocked(std::shared_ptr<InputApplicationHandle> application) REQUIRES(mLock);
+    bool onAnrLocked(const android::gui::FocusRequest& pendingFocusRequest) REQUIRES(mLock);
     void updateLastAnrStateLocked(const sp<android::gui::WindowInfoHandle>& window,
                                   const std::string& reason) REQUIRES(mLock);
     void updateLastAnrStateLocked(const InputApplicationHandle& application,
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 7ee6950..cd853a6 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -4718,6 +4718,36 @@
 
 // We have a focused application, but no focused window
 TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
+    FocusRequest request;
+    request.token = nullptr;
+    request.windowName = "";
+    request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+    request.displayId = mWindow->getInfo()->displayId;
+    mDispatcher->setFocusedWindow(request);
+    mWindow->consumeFocusEvent(false);
+
+    // taps on the window work as normal
+    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+                               WINDOW_LOCATION));
+    ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
+    mDispatcher->waitForIdle();
+    mFakePolicy->assertNotifyAnrWasNotCalled();
+
+    // Once a focused event arrives, we get an ANR for this application
+    // We specify the injection timeout to be smaller than the application timeout, to ensure that
+    // injection times out (instead of failing).
+    const InputEventInjectionResult result =
+            injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
+                      InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
+    ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
+    const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
+    mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
+    ASSERT_TRUE(mDispatcher->waitForIdle());
+}
+
+// We have a focused application, but we are waiting on the requested window to become focusable
+TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_PendingFocusedRequest) {
     mWindow->setFocusable(false);
     mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
     mWindow->consumeFocusEvent(false);
@@ -4738,7 +4768,7 @@
                       InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
     const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
+    mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
     ASSERT_TRUE(mDispatcher->waitForIdle());
 }
 
@@ -4788,11 +4818,10 @@
             injectKey(mDispatcher, AKEY_EVENT_ACTION_DOWN, 0 /* repeatCount */, ADISPLAY_ID_DEFAULT,
                       InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, false /* allowKeyRepeat */);
     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
-    const std::chrono::duration appTimeout =
-            mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(appTimeout, mApplication);
+    const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
+    mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
 
-    std::this_thread::sleep_for(appTimeout);
+    std::this_thread::sleep_for(timeout);
     // ANR should not be raised again. It is up to policy to do that if it desires.
     mFakePolicy->assertNotifyAnrWasNotCalled();
 
@@ -4813,8 +4842,8 @@
                       InputEventInjectionSync::WAIT_FOR_RESULT, 10ms);
     ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
 
-    const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
-    mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
+    const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
+    mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
 
     // Future focused events get dropped right away
     ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(mDispatcher));