diff options
author | 2022-02-23 23:40:57 +0000 | |
---|---|---|
committer | 2022-02-23 23:40:57 +0000 | |
commit | 9c3a23a50c58b6c3e11dbbd75c258302d61904dd (patch) | |
tree | b13a1f659ab4874144ceb5c02a39c3dd83b04f75 | |
parent | 924f7cb0b5e7430c8879ce01100edc3ea0a4f1aa (diff) | |
parent | 083bb215bffd974cc81e9de80ccfd452f845cf19 (diff) |
Merge "Support ANRs from windows that are not tracked by WM"
5 files changed, 170 insertions, 204 deletions
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index cd20a646a7..9691ad8a79 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -61,18 +61,13 @@ private: ALOGE("There is no focused window for %s", applicationHandle->getName().c_str()); } - void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, + void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid, const std::string& reason) override { ALOGE("Window is not responding: %s", reason.c_str()); } - 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 notifyWindowResponsive(const sp<IBinder>& connectionToken, + std::optional<int32_t> pid) override {} void notifyInputChannelBroken(const sp<IBinder>&) override {} diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 74ccf3fcdf..cecfc4dc03 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -5818,35 +5818,21 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingCommand(const sp<IBinder>& } } -void InputDispatcher::sendMonitorUnresponsiveCommandLocked(int32_t pid, std::string reason) { - auto command = [this, pid, reason = std::move(reason)]() REQUIRES(mLock) { - scoped_unlock unlock(mLock); - mPolicy->notifyMonitorUnresponsive(pid, reason); - }; - postCommandLocked(std::move(command)); -} - void InputDispatcher::sendWindowUnresponsiveCommandLocked(const sp<IBinder>& token, + std::optional<int32_t> pid, std::string reason) { - auto command = [this, token, reason = std::move(reason)]() REQUIRES(mLock) { + auto command = [this, token, pid, reason = std::move(reason)]() REQUIRES(mLock) { scoped_unlock unlock(mLock); - mPolicy->notifyWindowUnresponsive(token, reason); + mPolicy->notifyWindowUnresponsive(token, pid, reason); }; postCommandLocked(std::move(command)); } -void InputDispatcher::sendMonitorResponsiveCommandLocked(int32_t pid) { - auto command = [this, pid]() REQUIRES(mLock) { +void InputDispatcher::sendWindowResponsiveCommandLocked(const sp<IBinder>& token, + std::optional<int32_t> pid) { + auto command = [this, token, pid]() REQUIRES(mLock) { scoped_unlock unlock(mLock); - mPolicy->notifyMonitorResponsive(pid); - }; - postCommandLocked(std::move(command)); -} - -void InputDispatcher::sendWindowResponsiveCommandLocked(const sp<IBinder>& connectionToken) { - auto command = [this, connectionToken]() REQUIRES(mLock) { - scoped_unlock unlock(mLock); - mPolicy->notifyWindowResponsive(connectionToken); + mPolicy->notifyWindowResponsive(token, pid); }; postCommandLocked(std::move(command)); } @@ -5859,22 +5845,21 @@ void InputDispatcher::sendWindowResponsiveCommandLocked(const sp<IBinder>& conne void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& connection, std::string reason) { const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken(); + std::optional<int32_t> pid; 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; + pid = findMonitorPidByTokenLocked(connectionToken); + } else { + // The connection is a window + ALOGW("Window %s is unresponsive: %s", connection.inputChannel->getName().c_str(), + reason.c_str()); + const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken); + if (handle != nullptr) { + pid = handle->getInfo()->ownerPid; } - 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)); + sendWindowUnresponsiveCommandLocked(connectionToken, pid, std::move(reason)); } /** @@ -5882,18 +5867,17 @@ void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& conn */ void InputDispatcher::processConnectionResponsiveLocked(const Connection& connection) { const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken(); + std::optional<int32_t> pid; 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; + pid = findMonitorPidByTokenLocked(connectionToken); + } else { + // The connection is a window + const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken); + if (handle != nullptr) { + pid = handle->getInfo()->ownerPid; } - sendMonitorResponsiveCommandLocked(pid.value()); - return; } - // If not a monitor, must be a window - sendWindowResponsiveCommandLocked(connectionToken); + sendWindowResponsiveCommandLocked(connectionToken, pid); } bool InputDispatcher::afterKeyEventLockedInterruptable(const sp<Connection>& connection, diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index ae1e1d22f9..3c79c988c4 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -510,11 +510,11 @@ private: */ void processConnectionResponsiveLocked(const Connection& connection) REQUIRES(mLock); - void sendMonitorUnresponsiveCommandLocked(int32_t pid, std::string reason) REQUIRES(mLock); - void sendWindowUnresponsiveCommandLocked(const sp<IBinder>& connectionToken, std::string reason) + void sendWindowUnresponsiveCommandLocked(const sp<IBinder>& connectionToken, + std::optional<int32_t> pid, std::string reason) REQUIRES(mLock); - void sendMonitorResponsiveCommandLocked(int32_t pid) REQUIRES(mLock); - void sendWindowResponsiveCommandLocked(const sp<IBinder>& connectionToken) REQUIRES(mLock); + void sendWindowResponsiveCommandLocked(const sp<IBinder>& connectionToken, + std::optional<int32_t> pid) REQUIRES(mLock); // Optimization: AnrTracker is used to quickly find which connection is due for a timeout next. // AnrTracker must be kept in-sync with all responsive connection.waitQueues. diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index 3c1e6370b7..de0b6da884 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -51,30 +51,19 @@ public: const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) = 0; /* Notifies the system that a window just became unresponsive. This indicates that ANR - * 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 - * a response for. + * should be raised for this window. The window can be identified via its input token and the + * pid of the owner. The string reason contains information about the input event that we + * haven't received a response for. */ - virtual void notifyWindowUnresponsive(const sp<IBinder>& token, 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; + virtual void notifyWindowUnresponsive(const sp<IBinder>& token, std::optional<int32_t> pid, + const std::string& reason) = 0; /* Notifies the system that a window just became responsive. This is only called after the * window was first marked "unresponsive". This indicates that ANR dialog (if any) should * 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. - */ - virtual void notifyMonitorResponsive(int32_t pid) = 0; + virtual void notifyWindowResponsive(const sp<IBinder>& token, std::optional<int32_t> pid) = 0; /* Notifies the system that an input channel is unrecoverably broken. */ virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0; diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 1ffa875e57..3fb406c92c 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -90,6 +90,8 @@ static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) { class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface { InputDispatcherConfiguration mConfig; + using AnrResult = std::pair<sp<IBinder>, int32_t /*pid*/>; + protected: virtual ~FakeInputDispatcherPolicy() {} @@ -163,122 +165,71 @@ public: void assertNotifyNoFocusedWindowAnrWasCalled( std::chrono::nanoseconds timeout, const std::shared_ptr<InputApplicationHandle>& expectedApplication) { + std::unique_lock lock(mLock); + android::base::ScopedLockAssertion assumeLocked(mLock); std::shared_ptr<InputApplicationHandle> application; - { // acquire lock - std::unique_lock lock(mLock); - android::base::ScopedLockAssertion assumeLocked(mLock); - ASSERT_NO_FATAL_FAILURE( - application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock)); - } // release lock + ASSERT_NO_FATAL_FAILURE( + application = getAnrTokenLockedInterruptible(timeout, mAnrApplications, lock)); ASSERT_EQ(expectedApplication, application); } void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout, - const sp<IBinder>& expectedConnectionToken) { - sp<IBinder> connectionToken = getUnresponsiveWindowToken(timeout); - ASSERT_EQ(expectedConnectionToken, connectionToken); - } - - void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedConnectionToken) { - sp<IBinder> connectionToken = getResponsiveWindowToken(); - ASSERT_EQ(expectedConnectionToken, connectionToken); - } - - void assertNotifyMonitorUnresponsiveWasCalled(std::chrono::nanoseconds timeout) { - int32_t pid = getUnresponsiveMonitorPid(timeout); - ASSERT_EQ(MONITOR_PID, pid); + const sp<WindowInfoHandle>& window) { + LOG_ALWAYS_FATAL_IF(window == nullptr, "window should not be null"); + assertNotifyWindowUnresponsiveWasCalled(timeout, window->getToken(), + window->getInfo()->ownerPid); } - void assertNotifyMonitorResponsiveWasCalled() { - int32_t pid = getResponsiveMonitorPid(); - ASSERT_EQ(MONITOR_PID, pid); - } - - sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) { + void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout, + const sp<IBinder>& expectedToken, + int32_t expectedPid) { std::unique_lock lock(mLock); android::base::ScopedLockAssertion assumeLocked(mLock); - return getAnrTokenLockedInterruptible(timeout, mAnrWindowTokens, lock); + AnrResult result; + ASSERT_NO_FATAL_FAILURE(result = + getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock)); + const auto& [token, pid] = result; + ASSERT_EQ(expectedToken, token); + ASSERT_EQ(expectedPid, pid); } - sp<IBinder> getResponsiveWindowToken() { + /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */ + sp<IBinder> getUnresponsiveWindowToken(std::chrono::nanoseconds timeout) { std::unique_lock lock(mLock); android::base::ScopedLockAssertion assumeLocked(mLock); - return getAnrTokenLockedInterruptible(0s, mResponsiveWindowTokens, lock); + AnrResult result = getAnrTokenLockedInterruptible(timeout, mAnrWindows, lock); + const auto& [token, _] = result; + return token; } - int32_t getUnresponsiveMonitorPid(std::chrono::nanoseconds timeout) { + void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken, + int32_t expectedPid) { std::unique_lock lock(mLock); android::base::ScopedLockAssertion assumeLocked(mLock); - return getAnrTokenLockedInterruptible(timeout, mAnrMonitorPids, lock); + AnrResult result; + ASSERT_NO_FATAL_FAILURE( + result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock)); + const auto& [token, pid] = result; + ASSERT_EQ(expectedToken, token); + ASSERT_EQ(expectedPid, pid); } - int32_t getResponsiveMonitorPid() { + /** Wrap call with ASSERT_NO_FATAL_FAILURE() to ensure the return value is valid. */ + sp<IBinder> getResponsiveWindowToken() { std::unique_lock lock(mLock); android::base::ScopedLockAssertion assumeLocked(mLock); - return getAnrTokenLockedInterruptible(0s, mResponsiveMonitorPids, lock); - } - - // All three ANR-related callbacks behave the same way, so we use this generic function to wait - // for a specific container to become non-empty. When the container is non-empty, return the - // first entry from the container and erase it. - template <class T> - T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage, - std::unique_lock<std::mutex>& lock) REQUIRES(mLock) { - // If there is an ANR, Dispatcher won't be idle because there are still events - // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle - // before checking if ANR was called. - // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need - // to provide it some time to act. 100ms seems reasonable. - std::chrono::duration timeToWait = timeout + 100ms; // provide some slack - const std::chrono::time_point start = std::chrono::steady_clock::now(); - std::optional<T> token = - getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr); - if (!token.has_value()) { - ADD_FAILURE() << "Did not receive the ANR callback"; - return {}; - } - - const std::chrono::duration waited = std::chrono::steady_clock::now() - start; - // Ensure that the ANR didn't get raised too early. We can't be too strict here because - // the dispatcher started counting before this function was called - if (std::chrono::abs(timeout - waited) > 100ms) { - ADD_FAILURE() << "ANR was raised too early or too late. Expected " - << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count() - << "ms, but waited " - << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count() - << "ms instead"; - } - return *token; - } - - template <class T> - std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout, - std::queue<T>& storage, - std::unique_lock<std::mutex>& lock, - std::condition_variable& condition) - REQUIRES(mLock) { - condition.wait_for(lock, timeout, - [&storage]() REQUIRES(mLock) { return !storage.empty(); }); - if (storage.empty()) { - ADD_FAILURE() << "Did not receive the expected callback"; - return std::nullopt; - } - T item = storage.front(); - storage.pop(); - return std::make_optional(item); + AnrResult result = getAnrTokenLockedInterruptible(0s, mResponsiveWindows, lock); + const auto& [token, _] = result; + return token; } void assertNotifyAnrWasNotCalled() { std::scoped_lock lock(mLock); ASSERT_TRUE(mAnrApplications.empty()); - ASSERT_TRUE(mAnrWindowTokens.empty()); - ASSERT_TRUE(mAnrMonitorPids.empty()); - ASSERT_TRUE(mResponsiveWindowTokens.empty()) + ASSERT_TRUE(mAnrWindows.empty()); + ASSERT_TRUE(mResponsiveWindows.empty()) << "ANR was not called, but please also consume the 'connection is responsive' " "signal"; - ASSERT_TRUE(mResponsiveMonitorPids.empty()) - << "Monitor ANR was not called, but please also consume the 'monitor is responsive'" - " signal"; } void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) { @@ -346,10 +297,8 @@ private: // ANR handling std::queue<std::shared_ptr<InputApplicationHandle>> mAnrApplications GUARDED_BY(mLock); - std::queue<sp<IBinder>> mAnrWindowTokens GUARDED_BY(mLock); - std::queue<sp<IBinder>> mResponsiveWindowTokens GUARDED_BY(mLock); - std::queue<int32_t> mAnrMonitorPids GUARDED_BY(mLock); - std::queue<int32_t> mResponsiveMonitorPids GUARDED_BY(mLock); + std::queue<AnrResult> mAnrWindows GUARDED_BY(mLock); + std::queue<AnrResult> mResponsiveWindows GUARDED_BY(mLock); std::condition_variable mNotifyAnr; std::queue<sp<IBinder>> mBrokenInputChannels GUARDED_BY(mLock); std::condition_variable mNotifyInputChannelBroken; @@ -357,32 +306,74 @@ private: sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock); bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false; - void notifyConfigurationChanged(nsecs_t when) override { - std::scoped_lock lock(mLock); - mConfigurationChangedTime = when; + // All three ANR-related callbacks behave the same way, so we use this generic function to wait + // for a specific container to become non-empty. When the container is non-empty, return the + // first entry from the container and erase it. + template <class T> + T getAnrTokenLockedInterruptible(std::chrono::nanoseconds timeout, std::queue<T>& storage, + std::unique_lock<std::mutex>& lock) REQUIRES(mLock) { + // If there is an ANR, Dispatcher won't be idle because there are still events + // in the waitQueue that we need to check on. So we can't wait for dispatcher to be idle + // before checking if ANR was called. + // Since dispatcher is not guaranteed to call notifyNoFocusedWindowAnr right away, we need + // to provide it some time to act. 100ms seems reasonable. + std::chrono::duration timeToWait = timeout + 100ms; // provide some slack + const std::chrono::time_point start = std::chrono::steady_clock::now(); + std::optional<T> token = + getItemFromStorageLockedInterruptible(timeToWait, storage, lock, mNotifyAnr); + if (!token.has_value()) { + ADD_FAILURE() << "Did not receive the ANR callback"; + return {}; + } + + const std::chrono::duration waited = std::chrono::steady_clock::now() - start; + // Ensure that the ANR didn't get raised too early. We can't be too strict here because + // the dispatcher started counting before this function was called + if (std::chrono::abs(timeout - waited) > 100ms) { + ADD_FAILURE() << "ANR was raised too early or too late. Expected " + << std::chrono::duration_cast<std::chrono::milliseconds>(timeout).count() + << "ms, but waited " + << std::chrono::duration_cast<std::chrono::milliseconds>(waited).count() + << "ms instead"; + } + return *token; } - void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, const std::string&) override { - std::scoped_lock lock(mLock); - mAnrWindowTokens.push(connectionToken); - mNotifyAnr.notify_all(); + template <class T> + std::optional<T> getItemFromStorageLockedInterruptible(std::chrono::nanoseconds timeout, + std::queue<T>& storage, + std::unique_lock<std::mutex>& lock, + std::condition_variable& condition) + REQUIRES(mLock) { + condition.wait_for(lock, timeout, + [&storage]() REQUIRES(mLock) { return !storage.empty(); }); + if (storage.empty()) { + ADD_FAILURE() << "Did not receive the expected callback"; + return std::nullopt; + } + T item = storage.front(); + storage.pop(); + return std::make_optional(item); } - void notifyMonitorUnresponsive(int32_t pid, const std::string&) override { + void notifyConfigurationChanged(nsecs_t when) override { std::scoped_lock lock(mLock); - mAnrMonitorPids.push(pid); - mNotifyAnr.notify_all(); + mConfigurationChangedTime = when; } - void notifyWindowResponsive(const sp<IBinder>& connectionToken) override { + void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<int32_t> pid, + const std::string&) override { std::scoped_lock lock(mLock); - mResponsiveWindowTokens.push(connectionToken); + ASSERT_TRUE(pid.has_value()); + mAnrWindows.push({connectionToken, *pid}); mNotifyAnr.notify_all(); } - void notifyMonitorResponsive(int32_t pid) override { + void notifyWindowResponsive(const sp<IBinder>& connectionToken, + std::optional<int32_t> pid) override { std::scoped_lock lock(mLock); - mResponsiveMonitorPids.push(pid); + ASSERT_TRUE(pid.has_value()); + mResponsiveWindows.push({connectionToken, *pid}); mNotifyAnr.notify_all(); } @@ -1247,6 +1238,8 @@ public: mInfo.ownerUid = ownerUid; } + int32_t getPid() const { return mInfo.ownerPid; } + void destroyReceiver() { mInputReceiver = nullptr; } int getChannelFd() { return mInputReceiver->getChannelFd(); } @@ -4366,13 +4359,13 @@ TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) { std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); // ACTION_DOWN ASSERT_TRUE(sequenceNum); const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow); mWindow->finishEvent(*sequenceNum); mWindow->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT, 0 /*flags*/); ASSERT_TRUE(mDispatcher->waitForIdle()); - mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken()); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid()); } // Send a key to the app and have the app not respond right away. @@ -4382,7 +4375,7 @@ TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) { std::optional<uint32_t> sequenceNum = mWindow->receiveEvent(); ASSERT_TRUE(sequenceNum); const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow); ASSERT_TRUE(mDispatcher->waitForIdle()); } @@ -4519,7 +4512,7 @@ TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) // We have now sent down and up. Let's consume first event and then ANR on the second. mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT); const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow); } // A spy window can receive an ANR @@ -4534,13 +4527,13 @@ TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) { std::optional<uint32_t> sequenceNum = spy->receiveEvent(); // ACTION_DOWN ASSERT_TRUE(sequenceNum); const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy); spy->finishEvent(*sequenceNum); spy->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT, 0 /*flags*/); ASSERT_TRUE(mDispatcher->waitForIdle()); - mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken()); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid()); } // If an app is not responding to a key event, spy windows should continue to receive @@ -4555,7 +4548,7 @@ TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) // Stuck on the ACTION_UP const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow); // New tap will go to the spy window, but not to the window tapOnWindow(); @@ -4564,7 +4557,7 @@ TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT); // still the previous motion mDispatcher->waitForIdle(); - mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken()); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid()); mWindow->assertNoEvents(); spy->assertNoEvents(); } @@ -4581,7 +4574,7 @@ TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMoti mWindow->consumeMotionDown(); // Stuck on the ACTION_UP const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow); // New tap will go to the spy window, but not to the window tapOnWindow(); @@ -4590,7 +4583,7 @@ TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMoti mWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); // still the previous motion mDispatcher->waitForIdle(); - mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken()); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid()); mWindow->assertNoEvents(); spy->assertNoEvents(); } @@ -4608,13 +4601,13 @@ TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) { const std::optional<uint32_t> consumeSeq = monitor.receiveEvent(); ASSERT_TRUE(consumeSeq); - mFakePolicy->assertNotifyMonitorUnresponsiveWasCalled(30ms); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(30ms, monitor.getToken(), MONITOR_PID); monitor.finishEvent(*consumeSeq); monitor.consumeMotionCancel(ADISPLAY_ID_DEFAULT); ASSERT_TRUE(mDispatcher->waitForIdle()); - mFakePolicy->assertNotifyMonitorResponsiveWasCalled(); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID); } // If a window is unresponsive, then you get anr. if the window later catches up and starts to @@ -4629,19 +4622,19 @@ TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) { mWindow->consumeMotionDown(); // Block on ACTION_UP const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow); mWindow->consumeMotionUp(); // Now the connection should be healthy again mDispatcher->waitForIdle(); - mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken()); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid()); mWindow->assertNoEvents(); tapOnWindow(); mWindow->consumeMotionDown(); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow); mWindow->consumeMotionUp(); mDispatcher->waitForIdle(); - mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken()); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid()); mFakePolicy->assertNotifyAnrWasNotCalled(); mWindow->assertNoEvents(); } @@ -4654,7 +4647,7 @@ TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) { WINDOW_LOCATION)); const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow); std::this_thread::sleep_for(windowTimeout); // 'notifyConnectionUnresponsive' should only be called once per connection mFakePolicy->assertNotifyAnrWasNotCalled(); @@ -4664,7 +4657,7 @@ TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) { ADISPLAY_ID_DEFAULT, 0 /*flags*/); mWindow->assertNoEvents(); mDispatcher->waitForIdle(); - mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken()); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid()); mFakePolicy->assertNotifyAnrWasNotCalled(); } @@ -4826,7 +4819,7 @@ TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) { const std::chrono::duration timeout = mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow); // Because we injected two DOWN events in a row, CANCEL is enqueued for the first event // sequence to make it consistent mFocusedWindow->consumeMotionCancel(); @@ -4837,7 +4830,8 @@ TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) { mFocusedWindow->assertNoEvents(); mUnfocusedWindow->assertNoEvents(); ASSERT_TRUE(mDispatcher->waitForIdle()); - mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken()); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(), + mFocusedWindow->getPid()); mFakePolicy->assertNotifyAnrWasNotCalled(); } @@ -4851,8 +4845,9 @@ TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout tapOnFocusedWindow(); // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window - sp<IBinder> anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms); - sp<IBinder> anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms); + sp<IBinder> anrConnectionToken1, anrConnectionToken2; + ASSERT_NO_FATAL_FAILURE(anrConnectionToken1 = mFakePolicy->getUnresponsiveWindowToken(10ms)); + ASSERT_NO_FATAL_FAILURE(anrConnectionToken2 = mFakePolicy->getUnresponsiveWindowToken(0ms)); // We don't know which window will ANR first. But both of them should happen eventually. ASSERT_TRUE(mFocusedWindow->getToken() == anrConnectionToken1 || @@ -4867,8 +4862,9 @@ TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout mFocusedWindow->consumeMotionUp(); mUnfocusedWindow->consumeMotionOutside(); - sp<IBinder> responsiveToken1 = mFakePolicy->getResponsiveWindowToken(); - sp<IBinder> responsiveToken2 = mFakePolicy->getResponsiveWindowToken(); + sp<IBinder> responsiveToken1, responsiveToken2; + ASSERT_NO_FATAL_FAILURE(responsiveToken1 = mFakePolicy->getResponsiveWindowToken()); + ASSERT_NO_FATAL_FAILURE(responsiveToken2 = mFakePolicy->getResponsiveWindowToken()); // Both applications should be marked as responsive, in any order ASSERT_TRUE(mFocusedWindow->getToken() == responsiveToken1 || @@ -4892,7 +4888,7 @@ TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) { ASSERT_TRUE(upEventSequenceNum); const std::chrono::duration timeout = mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow); // Tap once again // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success @@ -4913,7 +4909,8 @@ TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) { // The second tap did not go to the focused window mFocusedWindow->assertNoEvents(); // Since all events are finished, connection should be deemed healthy again - mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken()); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(), + mFocusedWindow->getPid()); mFakePolicy->assertNotifyAnrWasNotCalled(); } @@ -5025,7 +5022,7 @@ TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) { const std::chrono::duration timeout = mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT); - mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow->getToken()); + mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow); mUnfocusedWindow->consumeMotionDown(); mFocusedWindow->consumeMotionDown(); @@ -5044,7 +5041,8 @@ TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) { ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction()); } ASSERT_TRUE(mDispatcher->waitForIdle()); - mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken()); + mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(), + mFocusedWindow->getPid()); mUnfocusedWindow->assertNoEvents(); mFocusedWindow->assertNoEvents(); |