summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vishnu Nair <vishnun@google.com> 2022-08-12 15:54:10 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-08-12 15:54:10 +0000
commitd2cd45d61cd51940ae417f63327c5ec0059ba385 (patch)
tree14fc8d8350872680088cd0e54154879c6c763457
parent70e6bdbfd4e6a0e01ca3456c0a709710cc58d709 (diff)
parent2f5bc8b8cfda7762213268842c13e2280ac02466 (diff)
Merge "InputDispatcher: Blame the window from the focus request for ANR"
-rw-r--r--services/inputflinger/dispatcher/FocusResolver.cpp2
-rw-r--r--services/inputflinger/dispatcher/FocusResolver.h2
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp26
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.h1
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp43
5 files changed, 65 insertions, 9 deletions
diff --git a/services/inputflinger/dispatcher/FocusResolver.cpp b/services/inputflinger/dispatcher/FocusResolver.cpp
index 4da846bcf8..85dcf8f4cf 100644
--- a/services/inputflinger/dispatcher/FocusResolver.cpp
+++ b/services/inputflinger/dispatcher/FocusResolver.cpp
@@ -39,7 +39,7 @@ sp<IBinder> FocusResolver::getFocusedWindowToken(int32_t displayId) const {
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 6d11a77aad..8a6dfa4ca9 100644
--- a/services/inputflinger/dispatcher/FocusResolver.h
+++ b/services/inputflinger/dispatcher/FocusResolver.h
@@ -62,6 +62,7 @@ public:
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 @@ private:
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 ff63967c2f..b52e3128db 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -659,6 +659,13 @@ void InputDispatcher::processNoFocusedWindowAnrLocked() {
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 @@ void InputDispatcher::sendDropWindowCommandLocked(const sp<IBinder>& token, floa
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 be619ae4c2..dc6dd5cdc0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -658,6 +658,7 @@ private:
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 7ee6950b09..cd853a64e1 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -4718,6 +4718,36 @@ TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
// 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 @@ TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
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 @@ TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr)
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 @@ TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
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));