diff options
| author | 2022-08-12 15:54:10 +0000 | |
|---|---|---|
| committer | 2022-08-12 15:54:10 +0000 | |
| commit | d2cd45d61cd51940ae417f63327c5ec0059ba385 (patch) | |
| tree | 14fc8d8350872680088cd0e54154879c6c763457 | |
| parent | 70e6bdbfd4e6a0e01ca3456c0a709710cc58d709 (diff) | |
| parent | 2f5bc8b8cfda7762213268842c13e2280ac02466 (diff) | |
Merge "InputDispatcher: Blame the window from the focus request for ANR"
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)); |