FocusResolver: Clean up focus requests and results when a display is removed
Prevents FocusResolver from leaking focus requests and results as
displays are added and removed.
Test: atest inputflinger_tests
Fixes: 188008394
Change-Id: I635b9becf91056fd540ab9d9546dd67a09324fc6
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index d2b8739..c0010ab 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4613,30 +4613,34 @@
}
{ // acquire lock
std::scoped_lock _l(mLock);
-
- std::shared_ptr<InputApplicationHandle> oldFocusedApplicationHandle =
- getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
-
- if (sharedPointersEqual(oldFocusedApplicationHandle, inputApplicationHandle)) {
- return; // This application is already focused. No need to wake up or change anything.
- }
-
- // Set the new application handle.
- if (inputApplicationHandle != nullptr) {
- mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
- } else {
- mFocusedApplicationHandlesByDisplay.erase(displayId);
- }
-
- // No matter what the old focused application was, stop waiting on it because it is
- // no longer focused.
- resetNoFocusedWindowTimeoutLocked();
+ setFocusedApplicationLocked(displayId, inputApplicationHandle);
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
mLooper->wake();
}
+void InputDispatcher::setFocusedApplicationLocked(
+ int32_t displayId, const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
+ std::shared_ptr<InputApplicationHandle> oldFocusedApplicationHandle =
+ getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
+
+ if (sharedPointersEqual(oldFocusedApplicationHandle, inputApplicationHandle)) {
+ return; // This application is already focused. No need to wake up or change anything.
+ }
+
+ // Set the new application handle.
+ if (inputApplicationHandle != nullptr) {
+ mFocusedApplicationHandlesByDisplay[displayId] = inputApplicationHandle;
+ } else {
+ mFocusedApplicationHandlesByDisplay.erase(displayId);
+ }
+
+ // No matter what the old focused application was, stop waiting on it because it is
+ // no longer focused.
+ resetNoFocusedWindowTimeoutLocked();
+}
+
/**
* Sets the focused display, which is responsible for receiving focus-dispatched input events where
* the display not specified.
@@ -6208,4 +6212,19 @@
mLock.lock();
}
+void InputDispatcher::displayRemoved(int32_t displayId) {
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+ // Set an empty list to remove all handles from the specific display.
+ setInputWindowsLocked(/* window handles */ {}, displayId);
+ setFocusedApplicationLocked(displayId, nullptr);
+ // Call focus resolver to clean up stale requests. This must be called after input windows
+ // have been removed for the removed display.
+ mFocusResolver.displayRemoved(displayId);
+ } // release lock
+
+ // Wake up poll loop since it may need to make new input dispatching choices.
+ mLooper->wake();
+}
+
} // namespace android::inputdispatcher