Loading core/java/android/view/SurfaceView.java +2 −7 Original line number Diff line number Diff line Loading @@ -366,13 +366,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall Log.e(TAG, "Received invalid input event"); return; } try { vri.processingBackKey(true); vri.enqueueInputEvent(keyEvent, null /* receiver */, 0 /* flags */, true /* processImmediately */); } finally { vri.processingBackKey(false); } }); } }; Loading core/java/android/view/ViewRootImpl.java +3 −17 Original line number Diff line number Diff line Loading @@ -727,8 +727,6 @@ public final class ViewRootImpl implements ViewParent, boolean mUpcomingWindowFocus; @GuardedBy("this") boolean mUpcomingInTouchMode; // While set, allow this VRI to handle back key without drop it. private boolean mProcessingBackKey; /** * Compatibility {@link OnBackInvokedCallback} for windowless window, to forward the back * key event host app. Loading Loading @@ -7269,7 +7267,7 @@ public final class ViewRootImpl implements ViewParent, // Find a reason for dropping or canceling the event. final String reason; // The embedded window is focused, allow this VRI to handle back key. if (!mAttachInfo.mHasWindowFocus && !(mProcessingBackKey && isBack(q.mEvent)) if (!mAttachInfo.mHasWindowFocus && !isBack(q.mEvent) && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER) && !isAutofillUiShowing()) { // This is a non-pointer event and the window doesn't currently have input focus Loading Loading @@ -11218,11 +11216,6 @@ public final class ViewRootImpl implements ViewParent, mHandler.obtainMessage(MSG_REQUEST_SCROLL_CAPTURE, listener).sendToTarget(); } // Make this VRI able to process back key without drop it. void processingBackKey(boolean processing) { mProcessingBackKey = processing; } /** * Collect and include any ScrollCaptureCallback instances registered with the window. * Loading Loading @@ -12554,15 +12547,8 @@ public final class ViewRootImpl implements ViewParent, * @return whether the event was handled (i.e. onKeyPreIme consumed it if preImeOnly=true) */ public boolean injectBackKeyEvents(boolean preImeOnly) { boolean consumed; try { processingBackKey(true); sendBackKeyEvent(KeyEvent.ACTION_DOWN, preImeOnly); consumed = sendBackKeyEvent(KeyEvent.ACTION_UP, preImeOnly); } finally { processingBackKey(false); } return consumed; return sendBackKeyEvent(KeyEvent.ACTION_UP, preImeOnly); } private boolean sendBackKeyEvent(int action, boolean preImeOnly) { services/core/java/com/android/server/wm/BackNavigationController.java +7 −8 Original line number Diff line number Diff line Loading @@ -166,15 +166,14 @@ class BackNavigationController { return null; } // Move focus to the top embedded window if possible if (mWindowManagerService.moveFocusToAdjacentEmbeddedWindow(window)) { window = wmService.getFocusedWindowLocked(); if (window == null) { Slog.e(TAG, "New focused window is null, returning null."); return null; // Updating the window to the most recently used one among the embedded windows // that are displayed adjacently, unless the IME is visible. // When the IME is visible, the IME is displayed on top of embedded activities. // In that case, the back event should still be delivered to focused activity in // order to dismiss the IME. if (!window.getDisplayContent().getImeContainer().isVisible()) { window = mWindowManagerService.getMostRecentUsedEmbeddedWindowForBack(window); } } if (!window.isDrawn()) { ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Focused window didn't have a valid surface drawn."); Loading services/core/java/com/android/server/wm/DisplayContent.java +16 −0 Original line number Diff line number Diff line Loading @@ -3894,6 +3894,22 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mTmpWindow; } /** * Returns the focused window of the given Activity if the Activity is focused. */ WindowState findFocusedWindow(ActivityRecord activityRecord) { final ActivityRecord tmpApp = mFocusedApp; mTmpWindow = null; try { mFocusedApp = activityRecord; // mFindFocusedWindow will populate mTmpWindow with the new focused window when found. activityRecord.forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */); } finally { mFocusedApp = tmpApp; } return mTmpWindow; } /** * Update the focused window and make some adjustments if the focus has changed. * Loading services/core/java/com/android/server/wm/WindowManagerService.java +54 −17 Original line number Diff line number Diff line Loading @@ -54,7 +54,6 @@ import static android.service.dreams.Flags.dreamHandlesConfirmKeys; import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; Loading Loading @@ -97,6 +96,7 @@ import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER; import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW; import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN; import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.window.WindowProviderService.isWindowProviderService; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; Loading Loading @@ -9377,40 +9377,77 @@ public class WindowManagerService extends IWindowManager.Stub } /** * Move focus to the adjacent embedded activity if the adjacent activity is more recently * created or has a window more recently added. * Returns the Activity that has the most recently created window in the adjacent activities * if any. */ boolean moveFocusToAdjacentEmbeddedWindow(@NonNull WindowState focusedWindow) { final TaskFragment taskFragment = focusedWindow.getTaskFragment(); @NonNull ActivityRecord getMostRecentActivityInAdjacent(@NonNull ActivityRecord focusedActivity) { final TaskFragment taskFragment = focusedActivity.getTaskFragment(); if (taskFragment == null) { // Skip if not an Activity window. return false; // Return if activity no attached. return focusedActivity; } if (!Flags.embeddedActivityBackNavFlag()) { // Skip if flag is not enabled. return false; // Return if flag is not enabled. return focusedActivity; } if (!focusedWindow.mActivityRecord.isEmbedded()) { // Skip if the focused activity is not embedded return false; if (!focusedActivity.isEmbedded()) { // Return if the focused activity is not embedded. return focusedActivity; } final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment(); final ActivityRecord adjacentTopActivity = adjacentTaskFragment != null ? adjacentTaskFragment.topRunningActivity() : null; if (adjacentTopActivity == null) { return false; // Return if no adjacent activity. return focusedActivity; } if (adjacentTopActivity.getLastWindowCreateTime() < focusedWindow.mActivityRecord.getLastWindowCreateTime()) { // Skip if the current focus activity has more recently active window. return false; < focusedActivity.getLastWindowCreateTime()) { // Return if the current focus activity has more recently active window. return focusedActivity; } return adjacentTopActivity; } moveFocusToActivity(adjacentTopActivity); @NonNull WindowState getMostRecentUsedEmbeddedWindowForBack(@NonNull WindowState focusedWindow) { final ActivityRecord focusedActivity = focusedWindow.getActivityRecord(); if (focusedActivity == null) { // Not an Activity. return focusedWindow; } final ActivityRecord mostRecentActivityInAdjacent = getMostRecentActivityInAdjacent( focusedActivity); if (mostRecentActivityInAdjacent == focusedActivity) { // Already be the most recent window. return focusedWindow; } // Looks for a candidate focused window on the adjacent Activity for the back event. final WindowState candidate = mostRecentActivityInAdjacent.getDisplayContent().findFocusedWindow( mostRecentActivityInAdjacent); return candidate != null ? candidate : focusedWindow; } /** * Move focus to the adjacent embedded activity if the adjacent activity is more recently * created or has a window more recently added. * <p> * Returns {@code true} if the focused window is changed. Otherwise, returns {@code false}. */ boolean moveFocusToAdjacentEmbeddedWindow(@NonNull WindowState focusedWindow) { final ActivityRecord mostRecentActivityInAdjacent = getMostRecentActivityInAdjacent( focusedWindow.getActivityRecord()); moveFocusToActivity(mostRecentActivityInAdjacent); return !focusedWindow.isFocused(); } Loading Loading
core/java/android/view/SurfaceView.java +2 −7 Original line number Diff line number Diff line Loading @@ -366,13 +366,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall Log.e(TAG, "Received invalid input event"); return; } try { vri.processingBackKey(true); vri.enqueueInputEvent(keyEvent, null /* receiver */, 0 /* flags */, true /* processImmediately */); } finally { vri.processingBackKey(false); } }); } }; Loading
core/java/android/view/ViewRootImpl.java +3 −17 Original line number Diff line number Diff line Loading @@ -727,8 +727,6 @@ public final class ViewRootImpl implements ViewParent, boolean mUpcomingWindowFocus; @GuardedBy("this") boolean mUpcomingInTouchMode; // While set, allow this VRI to handle back key without drop it. private boolean mProcessingBackKey; /** * Compatibility {@link OnBackInvokedCallback} for windowless window, to forward the back * key event host app. Loading Loading @@ -7269,7 +7267,7 @@ public final class ViewRootImpl implements ViewParent, // Find a reason for dropping or canceling the event. final String reason; // The embedded window is focused, allow this VRI to handle back key. if (!mAttachInfo.mHasWindowFocus && !(mProcessingBackKey && isBack(q.mEvent)) if (!mAttachInfo.mHasWindowFocus && !isBack(q.mEvent) && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER) && !isAutofillUiShowing()) { // This is a non-pointer event and the window doesn't currently have input focus Loading Loading @@ -11218,11 +11216,6 @@ public final class ViewRootImpl implements ViewParent, mHandler.obtainMessage(MSG_REQUEST_SCROLL_CAPTURE, listener).sendToTarget(); } // Make this VRI able to process back key without drop it. void processingBackKey(boolean processing) { mProcessingBackKey = processing; } /** * Collect and include any ScrollCaptureCallback instances registered with the window. * Loading Loading @@ -12554,15 +12547,8 @@ public final class ViewRootImpl implements ViewParent, * @return whether the event was handled (i.e. onKeyPreIme consumed it if preImeOnly=true) */ public boolean injectBackKeyEvents(boolean preImeOnly) { boolean consumed; try { processingBackKey(true); sendBackKeyEvent(KeyEvent.ACTION_DOWN, preImeOnly); consumed = sendBackKeyEvent(KeyEvent.ACTION_UP, preImeOnly); } finally { processingBackKey(false); } return consumed; return sendBackKeyEvent(KeyEvent.ACTION_UP, preImeOnly); } private boolean sendBackKeyEvent(int action, boolean preImeOnly) {
services/core/java/com/android/server/wm/BackNavigationController.java +7 −8 Original line number Diff line number Diff line Loading @@ -166,15 +166,14 @@ class BackNavigationController { return null; } // Move focus to the top embedded window if possible if (mWindowManagerService.moveFocusToAdjacentEmbeddedWindow(window)) { window = wmService.getFocusedWindowLocked(); if (window == null) { Slog.e(TAG, "New focused window is null, returning null."); return null; // Updating the window to the most recently used one among the embedded windows // that are displayed adjacently, unless the IME is visible. // When the IME is visible, the IME is displayed on top of embedded activities. // In that case, the back event should still be delivered to focused activity in // order to dismiss the IME. if (!window.getDisplayContent().getImeContainer().isVisible()) { window = mWindowManagerService.getMostRecentUsedEmbeddedWindowForBack(window); } } if (!window.isDrawn()) { ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Focused window didn't have a valid surface drawn."); Loading
services/core/java/com/android/server/wm/DisplayContent.java +16 −0 Original line number Diff line number Diff line Loading @@ -3894,6 +3894,22 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mTmpWindow; } /** * Returns the focused window of the given Activity if the Activity is focused. */ WindowState findFocusedWindow(ActivityRecord activityRecord) { final ActivityRecord tmpApp = mFocusedApp; mTmpWindow = null; try { mFocusedApp = activityRecord; // mFindFocusedWindow will populate mTmpWindow with the new focused window when found. activityRecord.forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */); } finally { mFocusedApp = tmpApp; } return mTmpWindow; } /** * Update the focused window and make some adjustments if the focus has changed. * Loading
services/core/java/com/android/server/wm/WindowManagerService.java +54 −17 Original line number Diff line number Diff line Loading @@ -54,7 +54,6 @@ import static android.service.dreams.Flags.dreamHandlesConfirmKeys; import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; Loading Loading @@ -97,6 +96,7 @@ import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED; import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_MULTIPLIER; import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_MISSING_WINDOW; import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_NOT_VISIBLE_ON_SCREEN; import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.window.WindowProviderService.isWindowProviderService; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; Loading Loading @@ -9377,40 +9377,77 @@ public class WindowManagerService extends IWindowManager.Stub } /** * Move focus to the adjacent embedded activity if the adjacent activity is more recently * created or has a window more recently added. * Returns the Activity that has the most recently created window in the adjacent activities * if any. */ boolean moveFocusToAdjacentEmbeddedWindow(@NonNull WindowState focusedWindow) { final TaskFragment taskFragment = focusedWindow.getTaskFragment(); @NonNull ActivityRecord getMostRecentActivityInAdjacent(@NonNull ActivityRecord focusedActivity) { final TaskFragment taskFragment = focusedActivity.getTaskFragment(); if (taskFragment == null) { // Skip if not an Activity window. return false; // Return if activity no attached. return focusedActivity; } if (!Flags.embeddedActivityBackNavFlag()) { // Skip if flag is not enabled. return false; // Return if flag is not enabled. return focusedActivity; } if (!focusedWindow.mActivityRecord.isEmbedded()) { // Skip if the focused activity is not embedded return false; if (!focusedActivity.isEmbedded()) { // Return if the focused activity is not embedded. return focusedActivity; } final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment(); final ActivityRecord adjacentTopActivity = adjacentTaskFragment != null ? adjacentTaskFragment.topRunningActivity() : null; if (adjacentTopActivity == null) { return false; // Return if no adjacent activity. return focusedActivity; } if (adjacentTopActivity.getLastWindowCreateTime() < focusedWindow.mActivityRecord.getLastWindowCreateTime()) { // Skip if the current focus activity has more recently active window. return false; < focusedActivity.getLastWindowCreateTime()) { // Return if the current focus activity has more recently active window. return focusedActivity; } return adjacentTopActivity; } moveFocusToActivity(adjacentTopActivity); @NonNull WindowState getMostRecentUsedEmbeddedWindowForBack(@NonNull WindowState focusedWindow) { final ActivityRecord focusedActivity = focusedWindow.getActivityRecord(); if (focusedActivity == null) { // Not an Activity. return focusedWindow; } final ActivityRecord mostRecentActivityInAdjacent = getMostRecentActivityInAdjacent( focusedActivity); if (mostRecentActivityInAdjacent == focusedActivity) { // Already be the most recent window. return focusedWindow; } // Looks for a candidate focused window on the adjacent Activity for the back event. final WindowState candidate = mostRecentActivityInAdjacent.getDisplayContent().findFocusedWindow( mostRecentActivityInAdjacent); return candidate != null ? candidate : focusedWindow; } /** * Move focus to the adjacent embedded activity if the adjacent activity is more recently * created or has a window more recently added. * <p> * Returns {@code true} if the focused window is changed. Otherwise, returns {@code false}. */ boolean moveFocusToAdjacentEmbeddedWindow(@NonNull WindowState focusedWindow) { final ActivityRecord mostRecentActivityInAdjacent = getMostRecentActivityInAdjacent( focusedWindow.getActivityRecord()); moveFocusToActivity(mostRecentActivityInAdjacent); return !focusedWindow.isFocused(); } Loading