diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 225c2094fd398..db4c3ea4cf064 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -954,8 +954,6 @@ class ActivityStack extends Task { void awakeFromSleepingLocked() { // Ensure activities are no longer sleeping. forAllActivities((Consumer) (r) -> r.setSleeping(false)); - ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, - false /* preserveWindows */); if (mPausingActivity != null) { Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause"); mPausingActivity.activityPaused(true); diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index 8260cb31acda0..2be3acc520580 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -253,6 +253,7 @@ public class DisplayArea extends WindowContainer { req = mLastKeyguardForcedOrientation; } } + mLastOrientationSource = win; return req; } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index c56440785bba5..2da2c29802315 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1189,6 +1189,8 @@ class DisplayContent extends WindowContainer // activity here. resumeFocusedStacksTopActivities(); } + // The visibility update must not be called before resuming the top, so the + // display orientation can be updated first if needed. Otherwise there may + // have redundant configuration changes due to apply outdated display + // orientation (from keyguard) to activity. + stack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, + false /* preserveWindows */); } } } diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index c3acb16dda49f..79f3b8340b214 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -1864,14 +1864,14 @@ final class TaskDisplayArea extends DisplayArea { @Override void dump(PrintWriter pw, String prefix, boolean dumpAll) { pw.println(prefix + "TaskDisplayArea " + getName()); - super.dump(pw, prefix, dumpAll); + final String doublePrefix = prefix + " "; + super.dump(pw, doublePrefix, dumpAll); if (mPreferredTopFocusableStack != null) { - pw.println(prefix + " mPreferredTopFocusableStack=" + mPreferredTopFocusableStack); + pw.println(doublePrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack); } if (mLastFocusedStack != null) { - pw.println(prefix + " mLastFocusedStack=" + mLastFocusedStack); + pw.println(doublePrefix + "mLastFocusedStack=" + mLastFocusedStack); } - final String doublePrefix = prefix + " "; final String triplePrefix = doublePrefix + " "; pw.println(doublePrefix + "Application tokens in top down Z order:"); for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) { diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index f984a8b024c14..0ade5867d0598 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2555,6 +2555,9 @@ class WindowContainer extends ConfigurationContainer< pw.print(prefix); pw.println("ContainerAnimator:"); mSurfaceAnimator.dump(pw, prefix + " "); } + if (mLastOrientationSource != null) { + pw.println(prefix + "mLastOrientationSource=" + mLastOrientationSource); + } } final void updateSurfacePosition() { diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 668f04785bbc5..c7b45efb2de18 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -127,8 +127,7 @@ public class ActivityRecordTests extends ActivityTestsBase { mTask = mStack.getBottomMostTask(); mActivity = mTask.getTopNonFinishingActivity(); - doReturn(false).when(mService).isBooting(); - doReturn(true).when(mService).isBooted(); + setBooted(mService); } @Test @@ -1535,7 +1534,7 @@ public class ActivityRecordTests extends ActivityTestsBase { * Sets orientation without notifying the parent to simulate that the display has not applied * the requested orientation yet. */ - private static void setRotatedScreenOrientationSilently(ActivityRecord r) { + static void setRotatedScreenOrientationSilently(ActivityRecord r) { final int rotatedOrentation = r.getConfiguration().orientation == ORIENTATION_PORTRAIT ? SCREEN_ORIENTATION_LANDSCAPE : SCREEN_ORIENTATION_PORTRAIT; diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index 37882bb2ba76b..1b42a0466cf73 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -1392,8 +1392,7 @@ public class ActivityStackTests extends ActivityTestsBase { } mSupervisor.endDeferResume(); - doReturn(false).when(mService).isBooting(); - doReturn(true).when(mService).isBooted(); + setBooted(mService); // 2 activities are started while keyguard is locked, so they are waiting to be resolved. assertFalse(unknownAppVisibilityController.allResolved()); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java index 64b5eca1beb82..f65d6e0c82af5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java @@ -67,8 +67,7 @@ public class ActivityTaskManagerServiceTests extends ActivityTestsBase { @Before public void setUp() throws Exception { - doReturn(false).when(mService).isBooting(); - doReturn(true).when(mService).isBooted(); + setBooted(mService); } /** Verify that activity is finished correctly upon request. */ 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 ddb186a1d2da5..23029017bac95 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1239,8 +1239,7 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testNoFixedRotationWithPip() { // Make resume-top really update the activity state. - doReturn(false).when(mWm.mAtmService).isBooting(); - doReturn(true).when(mWm.mAtmService).isBooted(); + setBooted(mWm.mAtmService); // Speed up the test by a few seconds. mWm.mAtmService.deferWindowLayout(); doNothing().when(mWm).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt()); diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java index 5dba004559132..51db099676b03 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java @@ -42,6 +42,7 @@ import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -57,8 +58,10 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; +import android.content.res.Configuration; import android.content.res.Resources; import android.platform.test.annotations.Presubmit; +import android.util.MergedConfiguration; import android.util.Pair; import androidx.test.filters.MediumTest; @@ -221,6 +224,35 @@ public class RootActivityContainerTests extends ActivityTestsBase { null /* target */, null /* targetOptions */); } + @Test + public void testAwakeFromSleepingWithAppConfiguration() { + final DisplayContent display = mRootWindowContainer.getDefaultDisplay(); + final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true).build(); + activity.moveFocusableActivityToTop("test"); + assertTrue(activity.getStack().isFocusedStackOnDisplay()); + ActivityRecordTests.setRotatedScreenOrientationSilently(activity); + + final Configuration rotatedConfig = new Configuration(); + display.computeScreenConfiguration(rotatedConfig, display.getDisplayRotation() + .rotationForOrientation(activity.getOrientation(), display.getRotation())); + assertNotEquals(activity.getConfiguration().orientation, rotatedConfig.orientation); + // Assume the activity was shown in different orientation. For example, the top activity is + // landscape and the portrait lockscreen is shown. + activity.setLastReportedConfiguration( + new MergedConfiguration(mService.getGlobalConfiguration(), rotatedConfig)); + activity.setState(ActivityState.STOPPED, "sleep"); + + display.setIsSleeping(true); + doReturn(false).when(display).shouldSleep(); + // Allow to resume when awaking. + setBooted(mService); + mRootWindowContainer.applySleepTokens(true); + + // The display orientation should be changed by the activity so there is no relaunch. + verify(activity, never()).relaunchActivityLocked(anyBoolean()); + assertEquals(rotatedConfig.orientation, display.getConfiguration().orientation); + } + /** * Verifies that removal of activity with task and stack is done correctly. */ diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java index d7462f810bb7c..53c2a5b8967d1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; + import android.os.Handler; import android.testing.DexmakerShareClassLoaderRule; @@ -66,6 +68,15 @@ class SystemServiceTestsBase { return mLockRule.waitForLocked(callable); } + /** + * Make the system booted, so that {@link ActivityStack#resumeTopActivityInnerLocked} can really + * be executed to update activity state and configuration when resuming the current top. + */ + static void setBooted(ActivityTaskManagerService atmService) { + doReturn(false).when(atmService).isBooting(); + doReturn(true).when(atmService).isBooted(); + } + /** * Utility class to compare the output of T#toString. It is convenient to have readable output * of assertion if the string content can represent the expected states.