Loading services/core/java/com/android/server/wm/BackNavigationController.java +3 −0 Original line number Diff line number Diff line Loading @@ -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. Loading services/core/java/com/android/server/wm/WindowManagerService.java +73 −25 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -5896,7 +5903,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; } Loading Loading @@ -7922,7 +7930,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 */); } } Loading Loading @@ -8997,21 +9006,60 @@ 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; } 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(); 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 // 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; } final WindowState w = t.getWindowState(); if (w != null) { final Task task = w.getTask(); Loading @@ -9021,8 +9069,7 @@ public class WindowManagerService extends IWindowManager.Stub } } ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s", t); ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s", t); if (mFocusedInputTarget != t && mFocusedInputTarget != null) { mFocusedInputTarget.handleTapOutsideFocusOutsideSelf(); } Loading @@ -9031,6 +9078,7 @@ public class WindowManagerService extends IWindowManager.Stub t.handleTapOutsideFocusInsideSelf(); mAtmService.mTaskSupervisor.mUserLeaving = false; } } @VisibleForTesting void handleTaskFocusChange(Task task, ActivityRecord touchedActivity) { Loading Loading
services/core/java/com/android/server/wm/BackNavigationController.java +3 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
services/core/java/com/android/server/wm/WindowManagerService.java +73 −25 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -5896,7 +5903,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; } Loading Loading @@ -7922,7 +7930,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 */); } } Loading Loading @@ -8997,21 +9006,60 @@ 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; } 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(); 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 // 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; } final WindowState w = t.getWindowState(); if (w != null) { final Task task = w.getTask(); Loading @@ -9021,8 +9069,7 @@ public class WindowManagerService extends IWindowManager.Stub } } ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s", t); ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s", t); if (mFocusedInputTarget != t && mFocusedInputTarget != null) { mFocusedInputTarget.handleTapOutsideFocusOutsideSelf(); } Loading @@ -9031,6 +9078,7 @@ public class WindowManagerService extends IWindowManager.Stub t.handleTapOutsideFocusInsideSelf(); mAtmService.mTaskSupervisor.mUserLeaving = false; } } @VisibleForTesting void handleTaskFocusChange(Task task, ActivityRecord touchedActivity) { Loading