diff options
| author | 2023-12-04 05:57:41 +0000 | |
|---|---|---|
| committer | 2023-12-04 05:57:41 +0000 | |
| commit | 6eb20a08bb78bf79778e2efc2487c395f16c59e5 (patch) | |
| tree | d6dde7e3afe5a6a3b454b73be470682c6bfdeb64 | |
| parent | f76b4a0d1edb9da4e50771abea5a4c7a1bc01d04 (diff) | |
| parent | b7693ffa15b5e4629c613d373d4bddd929c70ddb (diff) | |
Merge "Ensure activity configuration when applying WCT with display change" into main
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()); |