Request change transition for layout direction change for legacy

Before, we check if the bounds are resized to start a change transition
to avoid unnecessary screenshot. However, when the layout direction is
changed, we also want to have a change transition when the bounds are
not resized.

Bug: 241043533
Fix: 258130319
Test: atest WmTests:TaskFragmentTest
Change-Id: I413febe18c2288600066e9f8d641d6ab4ec5f126
This commit is contained in:
Chris Li
2022-12-05 16:52:22 +08:00
parent f2296dcb79
commit cc18bee6af
4 changed files with 96 additions and 13 deletions

View File

@@ -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);

View File

@@ -299,6 +299,14 @@ class TaskFragment extends WindowContainer<WindowContainer> {
@Nullable
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. */

View File

@@ -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;
}

View File

@@ -106,19 +106,50 @@ public class TaskFragmentTest extends WindowTestsBase {
verify(mTransaction).setWindowCrop(mLeash, 1000, 1000);
}
@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));
}
/**