@@ -155,7 +155,7 @@ static KeyEvent getTestKeyEvent() {
155155class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
156156 struct AnrResult {
157157 sp<IBinder> token{};
158- gui::Pid pid{gui::Pid::INVALID };
158+ std::optional< gui::Pid> pid{};
159159 };
160160 /* Stores data about a user-activity-poke event from the dispatcher. */
161161 struct UserActivityPokeEvent {
@@ -260,7 +260,7 @@ class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
260260
261261 void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
262262 const sp<IBinder>& expectedToken,
263- gui::Pid expectedPid) {
263+ std::optional< gui::Pid> expectedPid) {
264264 std::unique_lock lock(mLock);
265265 android::base::ScopedLockAssertion assumeLocked(mLock);
266266 AnrResult result;
@@ -280,7 +280,7 @@ class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
280280 }
281281
282282 void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
283- gui::Pid expectedPid) {
283+ std::optional< gui::Pid> expectedPid) {
284284 std::unique_lock lock(mLock);
285285 android::base::ScopedLockAssertion assumeLocked(mLock);
286286 AnrResult result;
@@ -524,16 +524,14 @@ class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
524524 void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
525525 const std::string&) override {
526526 std::scoped_lock lock(mLock);
527- ASSERT_TRUE(pid.has_value());
528- mAnrWindows.push({connectionToken, *pid});
527+ mAnrWindows.push({connectionToken, pid});
529528 mNotifyAnr.notify_all();
530529 }
531530
532531 void notifyWindowResponsive(const sp<IBinder>& connectionToken,
533532 std::optional<gui::Pid> pid) override {
534533 std::scoped_lock lock(mLock);
535- ASSERT_TRUE(pid.has_value());
536- mResponsiveWindows.push({connectionToken, *pid});
534+ mResponsiveWindows.push({connectionToken, pid});
537535 mNotifyAnr.notify_all();
538536 }
539537
@@ -9059,6 +9057,61 @@ TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
90599057 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
90609058}
90619059
9060+ // Send an event to the app and have the app not respond right away. Then remove the app window.
9061+ // When the window is removed, the dispatcher will cancel the events for that window.
9062+ // So InputDispatcher will enqueue ACTION_CANCEL event as well.
9063+ TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
9064+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9065+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9066+ {WINDOW_LOCATION}));
9067+
9068+ const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9069+ ASSERT_TRUE(sequenceNum);
9070+
9071+ // Remove the window, but the input channel should remain alive.
9072+ mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9073+
9074+ const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9075+ // Since the window was removed, Dispatcher does not know the PID associated with the window
9076+ // anymore, so the policy is notified without the PID.
9077+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
9078+ /*pid=*/std::nullopt);
9079+
9080+ mWindow->finishEvent(*sequenceNum);
9081+ // The cancellation was generated when the window was removed, along with the focus event.
9082+ mWindow->consumeMotionEvent(
9083+ AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9084+ mWindow->consumeFocusEvent(false);
9085+ ASSERT_TRUE(mDispatcher->waitForIdle());
9086+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9087+ }
9088+
9089+ // Send an event to the app and have the app not respond right away. Wait for the policy to be
9090+ // notified of the unresponsive window, then remove the app window.
9091+ TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
9092+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
9093+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
9094+ {WINDOW_LOCATION}));
9095+
9096+ const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
9097+ ASSERT_TRUE(sequenceNum);
9098+ const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9099+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
9100+
9101+ // Remove the window, but the input channel should remain alive.
9102+ mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9103+
9104+ mWindow->finishEvent(*sequenceNum);
9105+ // The cancellation was generated during the ANR, and the window lost focus when it was removed.
9106+ mWindow->consumeMotionEvent(
9107+ AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
9108+ mWindow->consumeFocusEvent(false);
9109+ ASSERT_TRUE(mDispatcher->waitForIdle());
9110+ // Since the window was removed, Dispatcher does not know the PID associated with the window
9111+ // becoming responsive, so the policy is notified without the PID.
9112+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
9113+ }
9114+
90629115class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
90639116 virtual void SetUp() override {
90649117 InputDispatcherTest::SetUp();
0 commit comments