From 4ffcb7183455d805384afe203a1fa56250cc83dd Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Thu, 30 Sep 2021 00:43:30 +0800 Subject: [PATCH] Put starting surface in task for embedded activity So the layer and position won't be disturbed by the parent activity. It also isolates the container effect such as the window won't be affected if the task fragment has crop. Bug: 201261613 Bug: 189385912 Test: atest ActivityRecordTests#testStartingWindowInTaskFragment Change-Id: Ifa866d26d31c655662f13aa5978078aa511ad116 --- .../com/android/server/wm/ActivityRecord.java | 13 ++++++-- .../server/wm/WindowManagerService.java | 12 +++---- .../com/android/server/wm/WindowState.java | 33 ++++++++++++++++++- .../server/wm/ActivityRecordTests.java | 6 +++- 4 files changed, 52 insertions(+), 12 deletions(-) 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.