diff options
4 files changed, 96 insertions, 13 deletions
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 89cad9c53464..6c6fbee885f2 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2098,6 +2098,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // from the client organizer, so the PIP activity can get the correct config // from the Task, and prevent conflict with the PipTaskOrganizer. tf.updateRequestedOverrideConfiguration(EMPTY); + tf.updateRelativeEmbeddedBounds(); } }); rootTask.setWindowingMode(WINDOWING_MODE_PINNED); diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 7eb9c16a25ff..454f338045d1 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -300,6 +300,14 @@ class TaskFragment extends WindowContainer<WindowContainer> { private final IBinder mFragmentToken; /** + * The bounds of the embedded TaskFragment relative to the parent Task. + * {@code null} if it is not {@link #mIsEmbedded} + * TODO(b/261785978) cleanup with legacy app transition + */ + @Nullable + private final Rect mRelativeEmbeddedBounds; + + /** * Whether to delay the call to {@link #updateOrganizedTaskFragmentSurface()} when there is a * configuration change. */ @@ -381,6 +389,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { mRootWindowContainer = mAtmService.mRootWindowContainer; mCreatedByOrganizer = createdByOrganizer; mIsEmbedded = isEmbedded; + mRelativeEmbeddedBounds = isEmbedded ? new Rect() : null; mTaskFragmentOrganizerController = mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController; mFragmentToken = fragmentToken; @@ -2419,16 +2428,53 @@ class TaskFragment extends WindowContainer<WindowContainer> { } } - /** Whether we should prepare a transition for this {@link TaskFragment} bounds change. */ - boolean shouldStartChangeTransition(Rect startBounds) { + /** + * Gets the relative bounds of this embedded TaskFragment. This should only be called on + * embedded TaskFragment. + */ + @NonNull + Rect getRelativeEmbeddedBounds() { + if (mRelativeEmbeddedBounds == null) { + throw new IllegalStateException("The TaskFragment is not embedded"); + } + return mRelativeEmbeddedBounds; + } + + /** + * Updates the record of the relative bounds of this embedded TaskFragment. This should only be + * called when the embedded TaskFragment's override bounds are changed. + * Returns {@code true} if the bounds is changed. + */ + void updateRelativeEmbeddedBounds() { + // We only record the override bounds, which means it will not be changed when it is filling + // Task, and resize with the parent. + getRequestedOverrideBounds(mTmpBounds); + getRelativePosition(mTmpPoint); + mTmpBounds.offsetTo(mTmpPoint.x, mTmpPoint.y); + mRelativeEmbeddedBounds.set(mTmpBounds); + } + + /** + * Updates the record of relative bounds of this embedded TaskFragment, and checks whether we + * should prepare a transition for the bounds change. + */ + boolean shouldStartChangeTransition(@NonNull Rect absStartBounds, + @NonNull Rect relStartBounds) { if (mTaskFragmentOrganizer == null || !canStartChangeTransition()) { return false; } - // Only take snapshot if the bounds are resized. - final Rect endBounds = getConfiguration().windowConfiguration.getBounds(); - return endBounds.width() != startBounds.width() - || endBounds.height() != startBounds.height(); + if (mTransitionController.isShellTransitionsEnabled()) { + // For Shell transition, the change will be collected anyway, so only take snapshot when + // the bounds are resized. + final Rect endBounds = getConfiguration().windowConfiguration.getBounds(); + return endBounds.width() != absStartBounds.width() + || endBounds.height() != absStartBounds.height(); + } else { + // For legacy transition, we need to trigger a change transition as long as the bounds + // is changed, even if it is not resized. + return !relStartBounds.equals(mRelativeEmbeddedBounds); + } } /** Records the starting bounds of the closing organized TaskFragment. */ diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index d85bd830cc11..5dacf42c176a 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -148,7 +148,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub @VisibleForTesting final ArrayMap<IBinder, TaskFragment> mLaunchTaskFragments = new ArrayMap<>(); - private final Rect mTmpBounds = new Rect(); + private final Rect mTmpBounds0 = new Rect(); + private final Rect mTmpBounds1 = new Rect(); WindowOrganizerController(ActivityTaskManagerService atm) { mService = atm; @@ -803,14 +804,15 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub // When the TaskFragment is resized, we may want to create a change transition for it, for // which we want to defer the surface update until we determine whether or not to start // change transition. - mTmpBounds.set(taskFragment.getBounds()); + mTmpBounds0.set(taskFragment.getBounds()); + mTmpBounds1.set(taskFragment.getRelativeEmbeddedBounds()); taskFragment.deferOrganizedTaskFragmentSurfaceUpdate(); final int effects = applyChanges(taskFragment, c, errorCallbackToken); - if (taskFragment.shouldStartChangeTransition(mTmpBounds)) { - taskFragment.initializeChangeTransition(mTmpBounds); + taskFragment.updateRelativeEmbeddedBounds(); + if (taskFragment.shouldStartChangeTransition(mTmpBounds0, mTmpBounds1)) { + taskFragment.initializeChangeTransition(mTmpBounds0); } taskFragment.continueOrganizedTaskFragmentSurfaceUpdate(); - mTmpBounds.set(0, 0, 0, 0); return effects; } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java index 38a712ed0435..11ac929327b9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -107,18 +107,49 @@ public class TaskFragmentTest extends WindowTestsBase { } @Test + public void testShouldStartChangeTransition_relativePositionChange() { + mockSurfaceFreezerSnapshot(mTaskFragment.mSurfaceFreezer); + final Rect startBounds = new Rect(0, 0, 500, 1000); + final Rect endBounds = new Rect(500, 0, 1000, 1000); + mTaskFragment.setBounds(startBounds); + mTaskFragment.updateRelativeEmbeddedBounds(); + doReturn(true).when(mTaskFragment).isVisible(); + doReturn(true).when(mTaskFragment).isVisibleRequested(); + + // Do not resize, just change the relative position. + final Rect relStartBounds = new Rect(mTaskFragment.getRelativeEmbeddedBounds()); + mTaskFragment.setBounds(endBounds); + mTaskFragment.updateRelativeEmbeddedBounds(); + spyOn(mDisplayContent.mTransitionController); + + // For Shell transition, we don't want to take snapshot when the bounds are not resized + doReturn(true).when(mDisplayContent.mTransitionController) + .isShellTransitionsEnabled(); + assertFalse(mTaskFragment.shouldStartChangeTransition(startBounds, relStartBounds)); + + // For legacy transition, we want to request a change transition even if it is just relative + // bounds change. + doReturn(false).when(mDisplayContent.mTransitionController) + .isShellTransitionsEnabled(); + assertTrue(mTaskFragment.shouldStartChangeTransition(startBounds, relStartBounds)); + } + + @Test public void testStartChangeTransition_resetSurface() { mockSurfaceFreezerSnapshot(mTaskFragment.mSurfaceFreezer); final Rect startBounds = new Rect(0, 0, 1000, 1000); final Rect endBounds = new Rect(500, 500, 1000, 1000); mTaskFragment.setBounds(startBounds); + mTaskFragment.updateRelativeEmbeddedBounds(); doReturn(true).when(mTaskFragment).isVisible(); doReturn(true).when(mTaskFragment).isVisibleRequested(); clearInvocations(mTransaction); + final Rect relStartBounds = new Rect(mTaskFragment.getRelativeEmbeddedBounds()); mTaskFragment.deferOrganizedTaskFragmentSurfaceUpdate(); mTaskFragment.setBounds(endBounds); - assertTrue(mTaskFragment.shouldStartChangeTransition(startBounds)); + mTaskFragment.updateRelativeEmbeddedBounds(); + assertTrue(mTaskFragment.shouldStartChangeTransition(startBounds, relStartBounds)); mTaskFragment.initializeChangeTransition(startBounds); mTaskFragment.continueOrganizedTaskFragmentSurfaceUpdate(); @@ -157,17 +188,20 @@ public class TaskFragmentTest extends WindowTestsBase { final Rect startBounds = new Rect(0, 0, 1000, 1000); final Rect endBounds = new Rect(500, 500, 1000, 1000); mTaskFragment.setBounds(startBounds); + mTaskFragment.updateRelativeEmbeddedBounds(); doReturn(true).when(mTaskFragment).isVisible(); doReturn(true).when(mTaskFragment).isVisibleRequested(); + final Rect relStartBounds = new Rect(mTaskFragment.getRelativeEmbeddedBounds()); final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); displayPolicy.screenTurnedOff(); assertFalse(mTaskFragment.okToAnimate()); mTaskFragment.setBounds(endBounds); + mTaskFragment.updateRelativeEmbeddedBounds(); - assertFalse(mTaskFragment.shouldStartChangeTransition(startBounds)); + assertFalse(mTaskFragment.shouldStartChangeTransition(startBounds, relStartBounds)); } /** |