Collect changes for transition right before updating config

Otherwise if display configuration is updated first, the later
collect() may not detect change. Such as if an activity with
ROTATION_ANIMATION_SEAMLESS is not included in TransitionInfo,
the animation will still be screenshot based style.

Bug: 240238575
Test: SeamlessAppRotationTest

Change-Id: I53f4212dad210cacdc4c243475ab1ab6355fe53b
This commit is contained in:
Riddle Hsu
2022-08-10 23:49:53 +08:00
parent 81ae41092e
commit 4cb5549a50
8 changed files with 25 additions and 49 deletions

View File

@@ -504,6 +504,7 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
mTransitionController.collectForDisplayAreaChange(this);
mTmpConfiguration.setTo(getConfiguration());
super.onConfigurationChanged(newParentConfig);

View File

@@ -5935,6 +5935,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (changes != 0) {
Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
+ mTempConfig + " for displayId=" + mDisplayId);
if (isReady() && mTransitionController.isShellTransitionsEnabled()) {
requestChangeTransitionIfNeeded(changes, null /* displayChange */);
}
onRequestedOverrideConfigurationChanged(mTempConfig);
final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
@@ -5951,9 +5954,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
mWmService.mDisplayNotificationController.dispatchDisplayChanged(
this, getConfiguration());
if (isReady() && mTransitionController.isShellTransitionsEnabled()) {
requestChangeTransitionIfNeeded(changes, null /* displayChange */);
}
}
return changes;
}

View File

@@ -513,19 +513,6 @@ public class DisplayRotation {
return true;
}
/**
* Utility to get a rotating displaycontent from a Transition.
* @return null if the transition doesn't contain a rotating display.
*/
static DisplayContent getDisplayFromTransition(Transition transition) {
for (int i = transition.mParticipants.size() - 1; i >= 0; --i) {
final WindowContainer wc = transition.mParticipants.valueAt(i);
if (!(wc instanceof DisplayContent)) continue;
return (DisplayContent) wc;
}
return null;
}
private void startRemoteRotation(int fromRotation, int toRotation) {
mDisplayContent.mRemoteDisplayChangeController.performRemoteDisplayChange(
fromRotation, toRotation, null /* newDisplayAreaInfo */,
@@ -545,11 +532,6 @@ public class DisplayRotation {
throw new IllegalStateException("Trying to rotate outside a transition");
}
mDisplayContent.mTransitionController.collect(mDisplayContent);
// Go through all tasks and collect them before the rotation
// TODO(shell-transitions): move collect() to onConfigurationChange once wallpaper
// handling is synchronized.
mDisplayContent.mTransitionController.collectForDisplayAreaChange(mDisplayContent,
null /* use collecting transition */);
}
mService.mAtmService.deferWindowLayout();
try {

View File

@@ -101,7 +101,6 @@ public class PhysicalDisplaySwitchTransitionLauncher {
if (t != null) {
mDisplayContent.mAtmService.startLaunchPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY);
mTransitionController.collectForDisplayAreaChange(mDisplayContent, t);
mTransition = t;
}
}

View File

@@ -1634,6 +1634,19 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
return mainWin.getAttrs().rotationAnimation;
}
/** Applies the new configuration and returns {@code true} if there is a display change. */
boolean applyDisplayChangeIfNeeded() {
boolean changed = false;
for (int i = mParticipants.size() - 1; i >= 0; --i) {
final WindowContainer<?> wc = mParticipants.valueAt(i);
final DisplayContent dc = wc.asDisplayContent();
if (dc == null || !mChanges.get(dc).hasChanged(dc)) continue;
dc.sendNewConfiguration();
changed = true;
}
return changed;
}
boolean getLegacyIsReady() {
return isCollecting() && mSyncId >= 0;
}

View File

@@ -463,13 +463,12 @@ class TransitionController {
}
/**
* Collects the window containers which need to be synced with the changing display (e.g.
* rotating) to the given transition or the current collecting transition.
* Collects the window containers which need to be synced with the changing display area into
* the current collecting transition.
*/
void collectForDisplayAreaChange(@NonNull DisplayArea<?> wc, @Nullable Transition incoming) {
if (incoming == null) incoming = mCollectingTransition;
if (incoming == null) return;
final Transition transition = incoming;
void collectForDisplayAreaChange(@NonNull DisplayArea<?> wc) {
final Transition transition = mCollectingTransition;
if (transition == null || !transition.mParticipants.contains(wc)) return;
// Collect all visible tasks.
wc.forAllLeafTasks(task -> {
if (task.isVisible()) {

View File

@@ -397,17 +397,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
mService.deferWindowLayout();
mService.mTaskSupervisor.setDeferRootVisibilityUpdate(true /* deferUpdate */);
try {
if (transition != null) {
// First check if we have a display rotation transition and if so, update it.
final DisplayContent dc = DisplayRotation.getDisplayFromTransition(transition);
if (dc != null && transition.mChanges.get(dc).hasChanged(dc)) {
// Go through all tasks and collect them before the rotation
// TODO(shell-transitions): move collect() to onConfigurationChange once
// wallpaper handling is synchronized.
dc.mTransitionController.collectForDisplayAreaChange(dc, transition);
dc.sendNewConfiguration();
effects |= TRANSACT_EFFECTS_LIFECYCLE;
}
if (transition != null && transition.applyDisplayChangeIfNeeded()) {
effects |= TRANSACT_EFFECTS_LIFECYCLE;
}
final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
final int hopSize = hops.size();
@@ -428,15 +419,6 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
addToSyncSet(syncId, wc);
}
if (transition != null) transition.collect(wc);
final DisplayArea da = wc.asDisplayArea();
// Only check DisplayArea here as a similar thing is done for DisplayContent above.
if (da != null && wc.asDisplayContent() == null
&& entry.getValue().getWindowingMode() != da.getWindowingMode()) {
// Go through all tasks and collect them before changing the windowing mode of a
// display-level container.
// TODO(shell-transitions): handle this more elegantly.
da.mTransitionController.collectForDisplayAreaChange(da, transition);
}
if ((entry.getValue().getChangeMask()
& WindowContainerTransaction.Change.CHANGE_FORCE_NO_PIP) != 0) {

View File

@@ -1904,10 +1904,10 @@ public class DisplayContentTests extends WindowTestsBase {
testPlayer.start();
assertNotEquals(origRot, dc.getConfiguration().windowConfiguration.getRotation());
assertNotNull(testPlayer.mLastReady);
assertEquals(dc, DisplayRotation.getDisplayFromTransition(testPlayer.mLastTransit));
WindowContainerToken dcToken = dc.mRemoteToken.toWindowContainerToken();
assertNotEquals(testPlayer.mLastReady.getChange(dcToken).getEndRotation(),
testPlayer.mLastReady.getChange(dcToken).getStartRotation());
assertTrue(testPlayer.mLastTransit.applyDisplayChangeIfNeeded());
testPlayer.finish();
}