summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java3
-rw-r--r--services/core/java/com/android/server/wm/Transition.java25
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java21
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java23
4 files changed, 58 insertions, 14 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 6f5c676187e1..b8b102faa7d4 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5280,6 +5280,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
/** Applies latest configuration and/or visibility updates if needed. */
boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
+ if (starting == null && mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
+ return true;
+ }
boolean kept = true;
final Task mainRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
// mainRootTask is null during startup.
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index e5604eca3df0..424394872821 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -2857,12 +2857,18 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
return false;
}
- /** Applies the new configuration for the changed displays. */
- void applyDisplayChangeIfNeeded() {
+ /**
+ * Applies the new configuration for the changed displays. Returns the activities that should
+ * check whether to deliver the new configuration to clients.
+ */
+ @Nullable
+ ArrayList<ActivityRecord> applyDisplayChangeIfNeeded() {
+ ArrayList<ActivityRecord> activitiesMayChange = null;
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()) continue;
+ final int originalSeq = dc.getConfiguration().seq;
dc.sendNewConfiguration();
// Set to ready if no other change controls the ready state. But if there is, such as
// if an activity is pausing, it will call setReady(ar, false) and wait for the next
@@ -2871,7 +2877,22 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
if (!mReadyTrackerOld.mUsed) {
setReady(dc, true);
}
+ if (originalSeq == dc.getConfiguration().seq) continue;
+ // If the update is deferred, sendNewConfiguration won't deliver new configuration to
+ // clients, then it is the caller's responsibility to deliver the changes.
+ if (mController.mAtm.mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
+ if (activitiesMayChange == null) {
+ activitiesMayChange = new ArrayList<>();
+ }
+ final ArrayList<ActivityRecord> visibleActivities = activitiesMayChange;
+ dc.forAllActivities(r -> {
+ if (r.isVisibleRequested()) {
+ visibleActivities.add(r);
+ }
+ });
+ }
}
+ return activitiesMayChange;
}
boolean getLegacyIsReady() {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 2af656942a2a..a872fd0baaae 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -570,8 +570,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
mService.deferWindowLayout();
mService.mTaskSupervisor.setDeferRootVisibilityUpdate(true /* deferUpdate */);
try {
- if (transition != null) {
- transition.applyDisplayChangeIfNeeded();
+ final ArrayList<ActivityRecord> activitiesMayChange =
+ transition != null ? transition.applyDisplayChangeIfNeeded() : null;
+ if (activitiesMayChange != null) {
+ effects |= TRANSACT_EFFECTS_CLIENT_CONFIG;
}
final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
final int hopSize = hops.size();
@@ -695,8 +697,23 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
haveConfigChanges.valueAt(i).forAllActivities(r -> {
r.ensureActivityConfiguration(0, PRESERVE_WINDOWS);
+ if (activitiesMayChange != null) {
+ activitiesMayChange.remove(r);
+ }
});
}
+ // TODO(b/258618073): Combine with haveConfigChanges after confirming that there
+ // is no problem to always preserve window. Currently this uses the parameters
+ // as ATMS#ensureConfigAndVisibilityAfterUpdate.
+ if (activitiesMayChange != null) {
+ for (int i = activitiesMayChange.size() - 1; i >= 0; --i) {
+ final ActivityRecord ar = activitiesMayChange.get(i);
+ if (!ar.isVisibleRequested()) continue;
+ ar.ensureActivityConfiguration(0 /* globalChanges */,
+ !PRESERVE_WINDOWS, true /* ignoreVisibility */,
+ false /* isRequestedOrientationChanged */);
+ }
+ }
}
if (effects != 0) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index acce2e2633bd..71d2504e1746 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -2086,15 +2086,17 @@ public class DisplayContentTests extends WindowTestsBase {
@Test
public void testShellTransitRotation() {
- DisplayContent dc = createNewDisplay();
- dc.setLastHasContent();
+ final DisplayContent dc = mDisplayContent;
+ // Create 2 visible activities to verify that they can both receive the new configuration.
+ final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ doReturn(true).when(activity1).isSyncFinished(any());
+ doReturn(true).when(activity2).isSyncFinished(any());
final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
final DisplayRotation dr = dc.getDisplayRotation();
- doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
- // Rotate 180 degree so the display doesn't have configuration change. This condition is
- // used for the later verification of stop-freezing (without setting mWaitingForConfig).
- doReturn((dr.getRotation() + 2) % 4).when(dr).rotationForOrientation(anyInt(), anyInt());
+ spyOn(dr);
+ doReturn((dr.getRotation() + 1) % 4).when(dr).rotationForOrientation(anyInt(), anyInt());
mWm.mDisplayChangeController =
new IDisplayChangeWindowController.Stub() {
@Override
@@ -2109,11 +2111,8 @@ public class DisplayContentTests extends WindowTestsBase {
}
};
- // kill any existing rotation animation (vestigial from test setup).
- dc.setRotationAnimation(null);
-
final int origRot = dc.getConfiguration().windowConfiguration.getRotation();
-
+ dc.setLastHasContent();
mWm.updateRotation(true /* alwaysSendConfiguration */, false /* forceRelayout */);
// Should create a transition request without performing rotation
assertNotNull(testPlayer.mLastRequest);
@@ -2122,6 +2121,10 @@ public class DisplayContentTests extends WindowTestsBase {
// Once transition starts, rotation is applied and transition shows DC rotating.
testPlayer.startTransition();
waitUntilHandlersIdle();
+ verify(activity1).ensureActivityConfiguration(anyInt(), anyBoolean(), anyBoolean(),
+ anyBoolean());
+ verify(activity2).ensureActivityConfiguration(anyInt(), anyBoolean(), anyBoolean(),
+ anyBoolean());
assertNotEquals(origRot, dc.getConfiguration().windowConfiguration.getRotation());
assertNotNull(testPlayer.mLastReady);
assertTrue(testPlayer.mController.isPlaying());