InputDispatcher: Fix multi-display Pointer Capture

There is an existing requirement that a window must both have focus and
be on the focused display to be able to gain Pointer Capture.

This means that focus changes on non-focused displays should not affect
Pointer Capture, and that a window must lose capture if its display
loses focus.

Verify these requirements with a test.

Bug: 342229227
Test: atest inputflinger_tests
Change-Id: I7b1c73b7759d8f20436ee401ba657a5dc8ead7a5
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 8de28c6..780bc13 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -11054,6 +11054,37 @@
     mWindow->assertNoEvents();
 }
 
+TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
+    // The default display is the focused display to begin with.
+    requestAndVerifyPointerCapture(mWindow, true);
+
+    // Move the second window to a second display, make it the focused window on that display.
+    mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
+    mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
+    setFocusedWindow(mSecondWindow);
+    mSecondWindow->consumeFocusEvent(true);
+
+    mWindow->assertNoEvents();
+
+    // The second window cannot gain capture because it is not on the focused display.
+    mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
+    mFakePolicy->assertSetPointerCaptureNotCalled();
+    mSecondWindow->assertNoEvents();
+
+    // Make the second display the focused display.
+    mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
+
+    // This causes the first window to lose pointer capture, and it's unable to request capture.
+    mWindow->consumeCaptureEvent(false);
+    mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
+
+    mDispatcher->requestPointerCapture(mWindow->getToken(), true);
+    mFakePolicy->assertSetPointerCaptureNotCalled();
+
+    // The second window is now able to gain pointer capture successfully.
+    requestAndVerifyPointerCapture(mSecondWindow, true);
+}
+
 using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
 
 TEST_F(InputDispatcherPointerCaptureDeathTest,