summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/BackNavigationController.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java98
2 files changed, 76 insertions, 25 deletions
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 14ae918129f7..4c0fee275d65 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -210,6 +210,9 @@ class BackNavigationController {
+ "topRunningActivity=%s, callbackInfo=%s, currentFocus=%s",
currentTask, currentActivity, callbackInfo, window);
+ // Clear the pointer down outside focus if any.
+ mWindowManagerService.clearPointerDownOutsideFocusRunnable();
+
// If we don't need to set up the animation, we return early. This is the case when
// - We have an application callback.
// - We don't have any ActivityRecord or Task to animate.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 521560936d81..98d1bf6b4dfd 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -732,6 +732,13 @@ public class WindowManagerService extends IWindowManager.Stub
final DisplayWindowListenerController mDisplayNotificationController;
final TaskSystemBarsListenerController mTaskSystemBarsListenerController;
+ /** Amount of time (in milliseconds) to delay the pointer down outside focus handling */
+ private static final int POINTER_DOWN_OUTSIDE_FOCUS_TIMEOUT_MS = 50;
+
+ /** A runnable to handle pointer down outside focus event. */
+ @Nullable
+ private Runnable mPointerDownOutsideFocusRunnable;
+
boolean mDisplayFrozen = false;
long mDisplayFreezeTime = 0;
int mLastDisplayFreezeDuration = 0;
@@ -5891,7 +5898,8 @@ public class WindowManagerService extends IWindowManager.Stub
case ON_POINTER_DOWN_OUTSIDE_FOCUS: {
synchronized (mGlobalLock) {
final IBinder touchedToken = (IBinder) msg.obj;
- onPointerDownOutsideFocusLocked(getInputTargetFromToken(touchedToken));
+ onPointerDownOutsideFocusLocked(getInputTargetFromToken(touchedToken),
+ true /* fromHandler */);
}
break;
}
@@ -7917,7 +7925,8 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized (mGlobalLock) {
final InputTarget inputTarget =
WindowManagerService.this.getInputTargetFromWindowTokenLocked(windowToken);
- WindowManagerService.this.onPointerDownOutsideFocusLocked(inputTarget);
+ WindowManagerService.this.onPointerDownOutsideFocusLocked(inputTarget,
+ false /* fromHandler */);
}
}
@@ -8972,39 +8981,78 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- private void onPointerDownOutsideFocusLocked(InputTarget t) {
+ void clearPointerDownOutsideFocusRunnable() {
+ if (mPointerDownOutsideFocusRunnable == null) return;
+
+ mH.removeCallbacks(mPointerDownOutsideFocusRunnable);
+ mPointerDownOutsideFocusRunnable = null;
+ }
+
+ private void onPointerDownOutsideFocusLocked(InputTarget t, boolean fromHandler) {
if (t == null || !t.receiveFocusFromTapOutside()) {
// If the window that received the input event cannot receive keys, don't move the
// display it's on to the top since that window won't be able to get focus anyway.
return;
}
- if (mRecentsAnimationController != null
- && mRecentsAnimationController.getTargetAppMainWindow() == t) {
- // If there is an active recents animation and touched window is the target, then ignore
- // the touch. The target already handles touches using its own input monitor and we
- // don't want to trigger any lifecycle changes from focusing another window.
- // TODO(b/186770026): We should remove this once we support multiple resumed activities
- // while in overview
- return;
- }
+ clearPointerDownOutsideFocusRunnable();
+
+ // For embedded activity that is showing side-by-side with another activity, delay
+ // handling the touch-outside event to prevent focus rapid changes back-n-forth.
+ // Otherwise, handle the touch-outside event directly.
final WindowState w = t.getWindowState();
- if (w != null) {
- final Task task = w.getTask();
- if (task != null && w.mTransitionController.isTransientHide(task)) {
- // Don't disturb transient animation by accident touch.
+ final ActivityRecord activity = w != null ? w.getActivityRecord() : null;
+ if (activity != null && activity.isEmbedded()
+ && activity.getTaskFragment().getAdjacentTaskFragment() != null) {
+ mPointerDownOutsideFocusRunnable = () -> handlePointerDownOutsideFocus(t);
+ 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);
+ mH.post(mPointerDownOutsideFocusRunnable);
+ } else {
+ handlePointerDownOutsideFocus(t);
+ }
+ }
+
+ private void handlePointerDownOutsideFocus(InputTarget t) {
+ synchronized (mGlobalLock) {
+ if (mPointerDownOutsideFocusRunnable != null
+ && mH.hasCallbacks(mPointerDownOutsideFocusRunnable)) {
+ // Skip if there's another pending pointer-down-outside-focus event.
+ return;
+ }
+ clearPointerDownOutsideFocusRunnable();
+
+ if (mRecentsAnimationController != null
+ && mRecentsAnimationController.getTargetAppMainWindow() == t) {
+ // If there is an active recents animation and touched window is the target,
+ // then ignore the touch. The target already handles touches using its own
+ // input monitor and we don't want to trigger any lifecycle changes from
+ // focusing another window.
+ // TODO(b/186770026): We should remove this once we support multiple resumed
+ // activities while in overview
return;
}
- }
- ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s",
- t);
- if (mFocusedInputTarget != t && mFocusedInputTarget != null) {
- mFocusedInputTarget.handleTapOutsideFocusOutsideSelf();
+ final WindowState w = t.getWindowState();
+ if (w != null) {
+ final Task task = w.getTask();
+ if (task != null && w.mTransitionController.isTransientHide(task)) {
+ // Don't disturb transient animation by accident touch.
+ return;
+ }
+ }
+
+ ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s", t);
+ if (mFocusedInputTarget != t && mFocusedInputTarget != null) {
+ mFocusedInputTarget.handleTapOutsideFocusOutsideSelf();
+ }
+ // Trigger Activity#onUserLeaveHint() if the order change of task pauses any activities.
+ mAtmService.mTaskSupervisor.mUserLeaving = true;
+ t.handleTapOutsideFocusInsideSelf();
+ mAtmService.mTaskSupervisor.mUserLeaving = false;
}
- // Trigger Activity#onUserLeaveHint() if the order change of task pauses any activities.
- mAtmService.mTaskSupervisor.mUserLeaving = true;
- t.handleTapOutsideFocusInsideSelf();
- mAtmService.mTaskSupervisor.mUserLeaving = false;
}
@VisibleForTesting