Skip handle pointer-down-outside-focus if input target changed
When TalkBack is enabled, the View#performClick is executed earlier
than the pointer-down-outside-focus event is handled. Therefore,
it is possible that the pointer-down-outside-focus is handled after
an Activity is already started, which unexpectedly changes the focus
again.
Bug: 381340445
Test: use Settings when Talkback is on
Flag: EXEMPT bugfix
Change-Id: Ib663e63b3c533b67f3d5a8cf51fe8cc5cb39f8e0
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a0c0b98..042bf01 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -9010,16 +9010,19 @@
clearPointerDownOutsideFocusRunnable();
+ final InputTarget focusedInputTarget = mFocusedInputTarget;
if (shouldDelayTouchOutside(t)) {
- mPointerDownOutsideFocusRunnable = () -> handlePointerDownOutsideFocus(t);
+ mPointerDownOutsideFocusRunnable =
+ () -> handlePointerDownOutsideFocus(t, focusedInputTarget);
mH.postDelayed(mPointerDownOutsideFocusRunnable, POINTER_DOWN_OUTSIDE_FOCUS_TIMEOUT_MS);
} else if (!fromHandler) {
// Still post the runnable to handler thread in case there is already a runnable
// in execution, but still waiting to hold the wm lock.
- mPointerDownOutsideFocusRunnable = () -> handlePointerDownOutsideFocus(t);
+ mPointerDownOutsideFocusRunnable =
+ () -> handlePointerDownOutsideFocus(t, focusedInputTarget);
mH.post(mPointerDownOutsideFocusRunnable);
} else {
- handlePointerDownOutsideFocus(t);
+ handlePointerDownOutsideFocus(t, focusedInputTarget);
}
}
@@ -9051,8 +9054,15 @@
return shouldDelayTouchForEmbeddedActivity || shouldDelayTouchForFreeform;
}
- private void handlePointerDownOutsideFocus(InputTarget t) {
+ private void handlePointerDownOutsideFocus(InputTarget t, InputTarget focusedInputTarget) {
synchronized (mGlobalLock) {
+ if (mFocusedInputTarget != focusedInputTarget) {
+ // Skip if the mFocusedInputTarget is already changed. This is possible if the
+ // pointer-down-outside-focus event is delayed to be handled.
+ ProtoLog.i(WM_DEBUG_FOCUS_LIGHT,
+ "Skip onPointerDownOutsideFocusLocked due to input target changed %s", t);
+ return;
+ }
if (mPointerDownOutsideFocusRunnable != null
&& mH.hasCallbacks(mPointerDownOutsideFocusRunnable)) {
// Skip if there's another pending pointer-down-outside-focus event.