Loading services/core/java/com/android/server/input/InputManagerService.java +9 −0 Original line number Diff line number Diff line Loading @@ -1846,6 +1846,7 @@ public class InputManagerService extends IInputManager.Stub // Native callback. private void onPointerDownOutsideFocus(IBinder touchedToken) { mWindowManagerCallbacks.onPointerDownOutsideFocus(touchedToken); } // Native callback. Loading Loading @@ -2060,6 +2061,14 @@ public class InputManagerService extends IInputManager.Stub public int getPointerLayer(); public int getPointerDisplayId(); /** * Notifies window manager that a {@link android.view.MotionEvent#ACTION_DOWN} pointer event * occurred on a window that did not have focus. * * @param touchedToken The token for the window that received the input event. */ void onPointerDownOutsideFocus(IBinder touchedToken); } /** Loading services/core/java/com/android/server/wm/InputManagerCallback.java +6 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.H.ON_POINTER_DOWN_OUTSIDE_FOCUS; import android.os.Debug; import android.os.IBinder; Loading Loading @@ -232,6 +233,11 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal } } @Override public void onPointerDownOutsideFocus(IBinder touchedToken) { mService.mH.obtainMessage(ON_POINTER_DOWN_OUTSIDE_FOCUS, touchedToken).sendToTarget(); } /** Waits until the built-in input devices have been configured. */ public boolean waitForInputDevicesReady(long timeoutMillis) { synchronized (mInputDevicesReadyMonitor) { Loading services/core/java/com/android/server/wm/TaskTapPointerEventListener.java +0 −71 Original line number Diff line number Diff line Loading @@ -22,12 +22,9 @@ import static android.view.PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW; import static android.view.PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW; import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW; import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; import android.os.Handler; import android.view.MotionEvent; import android.view.WindowManagerPolicyConstants.PointerEventListener; Loading @@ -40,67 +37,15 @@ import com.android.server.wm.WindowManagerService.H; public class TaskTapPointerEventListener implements PointerEventListener { private final Region mTouchExcludeRegion = new Region(); private final Region mTmpRegion = new Region(); private final WindowManagerService mService; private final DisplayContent mDisplayContent; private final Handler mHandler; private final Runnable mMoveDisplayToTop; private final Rect mTmpRect = new Rect(); private int mPointerIconType = TYPE_NOT_SPECIFIED; private int mLastDownX; private int mLastDownY; public TaskTapPointerEventListener(WindowManagerService service, DisplayContent displayContent) { mService = service; mDisplayContent = displayContent; mHandler = new Handler(mService.mH.getLooper()); mMoveDisplayToTop = () -> { int x; int y; synchronized (this) { x = mLastDownX; y = mLastDownY; } synchronized (mService.mGlobalLock) { if (!mService.mPerDisplayFocusEnabled && mService.mRoot.getTopFocusedDisplayContent() != mDisplayContent && inputMethodWindowContains(x, y)) { // In a single focus system, if the input method window and the input method // target window are on the different displays, when the user is tapping on the // input method window, we don't move its display to top. Otherwise, the input // method target window will lose the focus. return; } final Region windowTapExcludeRegion = Region.obtain(); mDisplayContent.amendWindowTapExcludeRegion(windowTapExcludeRegion); if (windowTapExcludeRegion.contains(x, y)) { windowTapExcludeRegion.recycle(); // The user is tapping on the window tap exclude region. We don't move this // display to top. A window tap exclude region, for example, may be set by an // ActivityView, and the region would match the bounds of both the ActivityView // and the virtual display in it. In this case, we would take the tap that is on // the embedded virtual display instead of this display. return; } windowTapExcludeRegion.recycle(); WindowContainer parent = mDisplayContent.getParent(); if (parent != null && parent.getTopChild() != mDisplayContent) { parent.positionChildAt(WindowContainer.POSITION_TOP, mDisplayContent, true /* includingParents */); // For compatibility, only the topmost activity is allowed to be resumed for // pre-Q app. Ensure the topmost activities are resumed whenever a display is // moved to top. // TODO(b/123761773): Investigate whether we can move this into // RootActivityContainer#updateTopResumedActivityIfNeeded(). Currently, it is // risky to do so because it seems possible to resume activities as part of a // larger transaction and it's too early to resume based on current order // when performing updateTopResumedActivityIfNeeded(). mDisplayContent.mAcitvityDisplay.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */); } } }; } @Override Loading @@ -115,9 +60,6 @@ public class TaskTapPointerEventListener implements PointerEventListener { mService.mTaskPositioningController.handleTapOutsideTask( mDisplayContent, x, y); } mLastDownX = x; mLastDownY = y; mHandler.post(mMoveDisplayToTop); } } break; Loading Loading @@ -178,17 +120,4 @@ public class TaskTapPointerEventListener implements PointerEventListener { mTouchExcludeRegion.set(newRegion); } } private int getDisplayId() { return mDisplayContent.getDisplayId(); } private boolean inputMethodWindowContains(int x, int y) { final WindowState inputMethodWindow = mDisplayContent.mInputMethodWindow; if (inputMethodWindow == null || !inputMethodWindow.isVisibleLw()) { return false; } inputMethodWindow.getTouchableRegion(mTmpRegion); return mTmpRegion.contains(x, y); } } services/core/java/com/android/server/wm/WindowManagerService.java +42 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN; import static com.android.server.LockGuard.INDEX_WINDOW; import static com.android.server.LockGuard.installLock; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; Loading Loading @@ -4519,6 +4520,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int SET_RUNNING_REMOTE_ANIMATION = 59; public static final int ANIMATION_FAILSAFE = 60; public static final int RECOMPUTE_FOCUS = 61; public static final int ON_POINTER_DOWN_OUTSIDE_FOCUS = 62; /** * Used to denote that an integer field in a message will not be used. Loading Loading @@ -4910,6 +4912,13 @@ public class WindowManagerService extends IWindowManager.Stub } break; } case ON_POINTER_DOWN_OUTSIDE_FOCUS: { synchronized (mGlobalLock) { final IBinder touchedToken = (IBinder) msg.obj; onPointerDownOutsideFocusLocked(touchedToken); } break; } } if (DEBUG_WINDOW_TRACE) { Slog.v(TAG_WM, "handleMessage: exit"); Loading Loading @@ -7569,4 +7578,37 @@ public class WindowManagerService extends IWindowManager.Stub mGlobalLock.notifyAll(); } } private void onPointerDownOutsideFocusLocked(IBinder touchedToken) { final WindowState touchedWindow = windowForClientLocked(null, touchedToken, false); if (touchedWindow == null) { return; } final DisplayContent displayContent = touchedWindow.getDisplayContent(); if (displayContent == null) { return; } if (!touchedWindow.canReceiveKeys()) { // 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; } final WindowContainer parent = displayContent.getParent(); if (parent != null && parent.getTopChild() != displayContent) { parent.positionChildAt(WindowContainer.POSITION_TOP, displayContent, true /* includingParents */); // For compatibility, only the topmost activity is allowed to be resumed for pre-Q // app. Ensure the topmost activities are resumed whenever a display is moved to top. // TODO(b/123761773): Investigate whether we can move this into // RootActivityContainer#updateTopResumedActivityIfNeeded(). Currently, it is risky // to do so because it seems possible to resume activities as part of a larger // transaction and it's too early to resume based on current order when performing // updateTopResumedActivityIfNeeded(). displayContent.mAcitvityDisplay.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */); } } } Loading
services/core/java/com/android/server/input/InputManagerService.java +9 −0 Original line number Diff line number Diff line Loading @@ -1846,6 +1846,7 @@ public class InputManagerService extends IInputManager.Stub // Native callback. private void onPointerDownOutsideFocus(IBinder touchedToken) { mWindowManagerCallbacks.onPointerDownOutsideFocus(touchedToken); } // Native callback. Loading Loading @@ -2060,6 +2061,14 @@ public class InputManagerService extends IInputManager.Stub public int getPointerLayer(); public int getPointerDisplayId(); /** * Notifies window manager that a {@link android.view.MotionEvent#ACTION_DOWN} pointer event * occurred on a window that did not have focus. * * @param touchedToken The token for the window that received the input event. */ void onPointerDownOutsideFocus(IBinder touchedToken); } /** Loading
services/core/java/com/android/server/wm/InputManagerCallback.java +6 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.H.ON_POINTER_DOWN_OUTSIDE_FOCUS; import android.os.Debug; import android.os.IBinder; Loading Loading @@ -232,6 +233,11 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal } } @Override public void onPointerDownOutsideFocus(IBinder touchedToken) { mService.mH.obtainMessage(ON_POINTER_DOWN_OUTSIDE_FOCUS, touchedToken).sendToTarget(); } /** Waits until the built-in input devices have been configured. */ public boolean waitForInputDevicesReady(long timeoutMillis) { synchronized (mInputDevicesReadyMonitor) { Loading
services/core/java/com/android/server/wm/TaskTapPointerEventListener.java +0 −71 Original line number Diff line number Diff line Loading @@ -22,12 +22,9 @@ import static android.view.PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW; import static android.view.PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW; import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW; import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; import android.graphics.Rect; import android.graphics.Region; import android.hardware.input.InputManager; import android.os.Handler; import android.view.MotionEvent; import android.view.WindowManagerPolicyConstants.PointerEventListener; Loading @@ -40,67 +37,15 @@ import com.android.server.wm.WindowManagerService.H; public class TaskTapPointerEventListener implements PointerEventListener { private final Region mTouchExcludeRegion = new Region(); private final Region mTmpRegion = new Region(); private final WindowManagerService mService; private final DisplayContent mDisplayContent; private final Handler mHandler; private final Runnable mMoveDisplayToTop; private final Rect mTmpRect = new Rect(); private int mPointerIconType = TYPE_NOT_SPECIFIED; private int mLastDownX; private int mLastDownY; public TaskTapPointerEventListener(WindowManagerService service, DisplayContent displayContent) { mService = service; mDisplayContent = displayContent; mHandler = new Handler(mService.mH.getLooper()); mMoveDisplayToTop = () -> { int x; int y; synchronized (this) { x = mLastDownX; y = mLastDownY; } synchronized (mService.mGlobalLock) { if (!mService.mPerDisplayFocusEnabled && mService.mRoot.getTopFocusedDisplayContent() != mDisplayContent && inputMethodWindowContains(x, y)) { // In a single focus system, if the input method window and the input method // target window are on the different displays, when the user is tapping on the // input method window, we don't move its display to top. Otherwise, the input // method target window will lose the focus. return; } final Region windowTapExcludeRegion = Region.obtain(); mDisplayContent.amendWindowTapExcludeRegion(windowTapExcludeRegion); if (windowTapExcludeRegion.contains(x, y)) { windowTapExcludeRegion.recycle(); // The user is tapping on the window tap exclude region. We don't move this // display to top. A window tap exclude region, for example, may be set by an // ActivityView, and the region would match the bounds of both the ActivityView // and the virtual display in it. In this case, we would take the tap that is on // the embedded virtual display instead of this display. return; } windowTapExcludeRegion.recycle(); WindowContainer parent = mDisplayContent.getParent(); if (parent != null && parent.getTopChild() != mDisplayContent) { parent.positionChildAt(WindowContainer.POSITION_TOP, mDisplayContent, true /* includingParents */); // For compatibility, only the topmost activity is allowed to be resumed for // pre-Q app. Ensure the topmost activities are resumed whenever a display is // moved to top. // TODO(b/123761773): Investigate whether we can move this into // RootActivityContainer#updateTopResumedActivityIfNeeded(). Currently, it is // risky to do so because it seems possible to resume activities as part of a // larger transaction and it's too early to resume based on current order // when performing updateTopResumedActivityIfNeeded(). mDisplayContent.mAcitvityDisplay.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */); } } }; } @Override Loading @@ -115,9 +60,6 @@ public class TaskTapPointerEventListener implements PointerEventListener { mService.mTaskPositioningController.handleTapOutsideTask( mDisplayContent, x, y); } mLastDownX = x; mLastDownY = y; mHandler.post(mMoveDisplayToTop); } } break; Loading Loading @@ -178,17 +120,4 @@ public class TaskTapPointerEventListener implements PointerEventListener { mTouchExcludeRegion.set(newRegion); } } private int getDisplayId() { return mDisplayContent.getDisplayId(); } private boolean inputMethodWindowContains(int x, int y) { final WindowState inputMethodWindow = mDisplayContent.mInputMethodWindow; if (inputMethodWindow == null || !inputMethodWindow.isVisibleLw()) { return false; } inputMethodWindow.getTouchableRegion(mTmpRegion); return mTmpRegion.contains(x, y); } }
services/core/java/com/android/server/wm/WindowManagerService.java +42 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN; import static com.android.server.LockGuard.INDEX_WINDOW; import static com.android.server.LockGuard.installLock; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT; Loading Loading @@ -4519,6 +4520,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int SET_RUNNING_REMOTE_ANIMATION = 59; public static final int ANIMATION_FAILSAFE = 60; public static final int RECOMPUTE_FOCUS = 61; public static final int ON_POINTER_DOWN_OUTSIDE_FOCUS = 62; /** * Used to denote that an integer field in a message will not be used. Loading Loading @@ -4910,6 +4912,13 @@ public class WindowManagerService extends IWindowManager.Stub } break; } case ON_POINTER_DOWN_OUTSIDE_FOCUS: { synchronized (mGlobalLock) { final IBinder touchedToken = (IBinder) msg.obj; onPointerDownOutsideFocusLocked(touchedToken); } break; } } if (DEBUG_WINDOW_TRACE) { Slog.v(TAG_WM, "handleMessage: exit"); Loading Loading @@ -7569,4 +7578,37 @@ public class WindowManagerService extends IWindowManager.Stub mGlobalLock.notifyAll(); } } private void onPointerDownOutsideFocusLocked(IBinder touchedToken) { final WindowState touchedWindow = windowForClientLocked(null, touchedToken, false); if (touchedWindow == null) { return; } final DisplayContent displayContent = touchedWindow.getDisplayContent(); if (displayContent == null) { return; } if (!touchedWindow.canReceiveKeys()) { // 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; } final WindowContainer parent = displayContent.getParent(); if (parent != null && parent.getTopChild() != displayContent) { parent.positionChildAt(WindowContainer.POSITION_TOP, displayContent, true /* includingParents */); // For compatibility, only the topmost activity is allowed to be resumed for pre-Q // app. Ensure the topmost activities are resumed whenever a display is moved to top. // TODO(b/123761773): Investigate whether we can move this into // RootActivityContainer#updateTopResumedActivityIfNeeded(). Currently, it is risky // to do so because it seems possible to resume activities as part of a larger // transaction and it's too early to resume based on current order when performing // updateTopResumedActivityIfNeeded(). displayContent.mAcitvityDisplay.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */); } } }