diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 168686c04d367..db44dd8f70d17 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1482,7 +1482,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // The starting window should keep covering its task when the activity is // reparented to a task fragment that may not fill the task bounds. associateStartingDataWithTask(); - overrideConfigurationPropagation(mStartingWindow, task); + attachStartingSurfaceToAssociatedTask(); } mImeInsetsFrozenUntilStartInput = false; } @@ -2383,13 +2383,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } void attachStartingWindow(@NonNull WindowState startingWindow) { + startingWindow.mStartingData = mStartingData; mStartingWindow = startingWindow; if (mStartingData != null && mStartingData.mAssociatedTask != null) { - // Associate the configuration of starting window with the task. - overrideConfigurationPropagation(startingWindow, mStartingData.mAssociatedTask); + attachStartingSurfaceToAssociatedTask(); } } + private void attachStartingSurfaceToAssociatedTask() { + // Associate the configuration of starting window with the task. + overrideConfigurationPropagation(mStartingWindow, mStartingData.mAssociatedTask); + getSyncTransaction().reparent(mStartingWindow.mSurfaceControl, + mStartingData.mAssociatedTask.mSurfaceControl); + } + private void associateStartingDataWithTask() { mStartingData.mAssociatedTask = task; task.forAllActivities(r -> { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b9c6e1bd73cea..0e99c0f1bad02 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1770,17 +1770,15 @@ public class WindowManagerService extends IWindowManager.Stub final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty(); win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows); - if (type == TYPE_APPLICATION_STARTING && activity != null) { - activity.attachStartingWindow(win); - ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s", - activity, win); - } - boolean imMayMove = true; win.mToken.addWindow(win); displayPolicy.addWindowLw(win, attrs); - if (type == TYPE_INPUT_METHOD) { + if (type == TYPE_APPLICATION_STARTING && activity != null) { + activity.attachStartingWindow(win); + ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s", + activity, win); + } else if (type == TYPE_INPUT_METHOD) { displayContent.setInputMethodWindowLocked(win); imMayMove = false; } else if (type == TYPE_INPUT_METHOD_DIALOG) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c3d51d5d4d1da..3adecf3474ebc 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -308,6 +308,8 @@ class WindowState extends WindowContainer implements WindowManagerP @NonNull WindowToken mToken; // The same object as mToken if this is an app window and null for non-app windows. ActivityRecord mActivityRecord; + /** Non-null if this is a starting window. */ + StartingData mStartingData; // mAttrs.flags is tested in animation without being locked. If the bits tested are ever // modified they will need to be locked. @@ -5485,6 +5487,10 @@ class WindowState extends WindowContainer implements WindowManagerP return mWillReplaceWindow; } + private boolean isStartingWindowAssociatedToTask() { + return mStartingData != null && mStartingData.mAssociatedTask != null; + } + private void applyDims() { if (!mAnimatingExit && mAppDied) { mIsDimming = true; @@ -5634,7 +5640,9 @@ class WindowState extends WindowContainer implements WindowManagerP outPoint.offset(-parent.mWindowFrames.mFrame.left + mTmpPoint.x, -parent.mWindowFrames.mFrame.top + mTmpPoint.y); } else if (parentWindowContainer != null) { - final Rect parentBounds = parentWindowContainer.getBounds(); + final Rect parentBounds = isStartingWindowAssociatedToTask() + ? mStartingData.mAssociatedTask.getBounds() + : parentWindowContainer.getBounds(); outPoint.offset(-parentBounds.left, -parentBounds.top); } @@ -5717,6 +5725,11 @@ class WindowState extends WindowContainer implements WindowManagerP @Override void assignLayer(Transaction t, int layer) { + if (isStartingWindowAssociatedToTask()) { + // The starting window should cover the task. + t.setLayer(mSurfaceControl, Integer.MAX_VALUE); + return; + } // See comment in assignRelativeLayerForImeTargetChild if (needsRelativeLayeringToIme()) { getDisplayContent().assignRelativeLayerForImeTargetChild(t, this); @@ -5729,6 +5742,24 @@ class WindowState extends WindowContainer implements WindowManagerP return mIsDimming; } + @Override + protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) { + if (isStartingWindowAssociatedToTask()) { + // Its surface is already put in task. Don't reparent when transferring starting window + // across activities. + return; + } + super.reparentSurfaceControl(t, newParent); + } + + @Override + public SurfaceControl getAnimationLeashParent() { + if (isStartingWindowAssociatedToTask()) { + return mStartingData.mAssociatedTask.mSurfaceControl; + } + return super.getAnimationLeashParent(); + } + // TODO(b/70040778): We should aim to eliminate the last user of TYPE_APPLICATION_MEDIA // then we can drop all negative layering on the windowing side and simply inherit // the default implementation here. diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index c434b137317ec..65733d7a41295 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -2700,8 +2700,8 @@ public class ActivityRecordTests extends WindowTestsBase { final WindowState startingWindow = createWindowState( new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING), activity1); activity1.addWindow(startingWindow); - activity1.attachStartingWindow(startingWindow); activity1.mStartingData = mock(StartingData.class); + activity1.attachStartingWindow(startingWindow); final Task task = activity1.getTask(); final Rect taskBounds = task.getBounds(); final int width = taskBounds.width(); @@ -2729,6 +2729,10 @@ public class ActivityRecordTests extends WindowTestsBase { assertTrue(activity2.isResizeable()); activity1.reparent(taskFragment1, POSITION_TOP); + verify(activity1.getSyncTransaction()).reparent(eq(startingWindow.mSurfaceControl), + eq(task.mSurfaceControl)); + assertEquals(activity1.mStartingData, startingWindow.mStartingData); + assertEquals(task.mSurfaceControl, startingWindow.getAnimationLeashParent()); assertEquals(task, activity1.mStartingData.mAssociatedTask); assertEquals(taskFragment1.getBounds(), activity1.getBounds()); // The activity was resized by task fragment, but starting window must still cover the task.