Update visibility and config at the same time
Update visibility, orientation and config together to ensure that
only activities that are actually visible can affect the orientation.
Bug: 76011287
Test: ActivityManagerAppConfigurationTests
Change-Id: Icdafedf540391d186f5dbe250b2b69d36742a26c
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index aaa5161..3ad461f 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1360,7 +1360,9 @@
}
void goToSleep() {
- ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ // Ensure visibility without updating configuration, as activities are about to sleep.
+ ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS,
+ false /* updateConfiguration */);
// Make sure any paused or stopped but visible activities are now sleeping.
// This ensures that the activity's onStop() is called.
@@ -1829,12 +1831,23 @@
}
/**
- * Make sure that all activities that need to be visible (that is, they
- * currently can be seen by the user) actually are.
+ * Make sure that all activities that need to be visible in the stack (that is, they
+ * currently can be seen by the user) actually are and update their configuration.
+ */
+ final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+ boolean preserveWindows) {
+ ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
+ true /* updateConfiguration */);
+ }
+
+ /**
+ * Ensure visibility with an option to also update the configuration of visible activities.
+ * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
+ * @see ActivityStackSupervisor#ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
*/
// TODO: Should be re-worked based on the fact that each task as a stack in most cases.
final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
- boolean preserveWindows) {
+ boolean preserveWindows, boolean updateConfiguration) {
mTopActivityOccludesKeyguard = false;
mTopDismissingKeyguardActivity = null;
mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
@@ -1886,9 +1899,7 @@
+ " finishing=" + r.finishing + " state=" + r.getState());
// First: if this is not the current activity being started, make
// sure it matches the current configuration.
- if (r != starting) {
- // Ensure activity configuration ignoring stop state since we are
- // becoming visible.
+ if (r != starting && updateConfiguration) {
r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows,
true /* ignoreStopState */);
}
@@ -2608,25 +2619,16 @@
boolean notUpdated = true;
if (mStackSupervisor.isFocusedStack(this)) {
-
- // We have special rotation behavior when Keyguard is locked. Make sure all
- // activity visibilities are set correctly as well as the transition is updated
- // if needed to get the correct rotation behavior.
+ // We have special rotation behavior when here is some active activity that
+ // requests specific orientation or Keyguard is locked. Make sure all activity
+ // visibilities are set correctly as well as the transition is updated if needed
+ // to get the correct rotation behavior. Otherwise the following call to update
+ // the orientation may cause incorrect configurations delivered to client as a
+ // result of invisible window resize.
// TODO: Remove this once visibilities are set correctly immediately when
// starting an activity.
- if (mStackSupervisor.getKeyguardController().isKeyguardLocked()) {
- mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */,
- 0 /* configChanges */, false /* preserveWindows */);
- }
- final Configuration config = mWindowManager.updateOrientationFromAppTokens(
- mStackSupervisor.getDisplayOverrideConfiguration(mDisplayId),
- next.mayFreezeScreenLocked(next.app) ? next.appToken : null,
- mDisplayId);
- if (config != null) {
- next.frozenBeforeDestroy = true;
- }
- notUpdated = !mService.updateDisplayOverrideConfigurationLocked(config, next,
- false /* deferResume */, mDisplayId);
+ notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
+ true /* markFrozenIfConfigChanged */, false /* deferResume */);
}
if (notUpdated) {
@@ -3834,7 +3836,8 @@
if (finishingActivityInNonFocusedStack) {
// Finishing activity that was in paused state and it was in not currently focused
// stack, need to make something visible in its place.
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mStackSupervisor.ensureVisibilityAndConfig(null, mDisplayId,
+ false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
if (activityRemoved) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 7310fab..f18f236 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1409,15 +1409,11 @@
// manager with a new orientation. We don't care about that, because the activity is
// not currently running so we are just restarting it anyway.
if (checkConfig) {
- final int displayId = r.getDisplayId();
- final Configuration config = mWindowManager.updateOrientationFromAppTokens(
- getDisplayOverrideConfiguration(displayId),
- r.mayFreezeScreenLocked(app) ? r.appToken : null, displayId);
// Deferring resume here because we're going to launch new activity shortly.
// We don't want to perform a redundant launch of the same record while ensuring
// configurations and trying to resume top activity of focused stack.
- mService.updateDisplayOverrideConfigurationLocked(config, r, true /* deferResume */,
- displayId);
+ ensureVisibilityAndConfig(r, r.getDisplayId(),
+ false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,
@@ -1630,6 +1626,31 @@
return true;
}
+ /**
+ * Ensure all activities visibility, update orientation and configuration.
+ */
+ boolean ensureVisibilityAndConfig(ActivityRecord r, int displayId,
+ boolean markFrozenIfConfigChanged, boolean deferResume) {
+ // First ensure visibility without updating the config just yet. We need this to know what
+ // activities are affecting configuration now.
+ ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
+ false /* preserveWindows */, false /* updateConfiguration */);
+
+ // Force-update the orientation from the WindowManager, since we need the true configuration
+ // to send to the client now.
+ final Configuration config = mWindowManager.updateOrientationFromAppTokens(
+ getDisplayOverrideConfiguration(displayId),
+ r != null && r.mayFreezeScreenLocked(r.app) ? r.appToken : null,
+ displayId);
+ if (r != null && markFrozenIfConfigChanged && config != null) {
+ r.frozenBeforeDestroy = true;
+ }
+
+ // Update the configuration of the activities on the display.
+ return mService.updateDisplayOverrideConfigurationLocked(config, r,
+ deferResume, displayId);
+ }
+
private void logIfTransactionTooLarge(Intent intent, Bundle icicle) {
int extrasSize = 0;
if (intent != null) {
@@ -3647,8 +3668,21 @@
mHandler.obtainMessage(LAUNCH_TASK_BEHIND_COMPLETE, token).sendToTarget();
}
+ /**
+ * Make sure that all activities that need to be visible in the system actually are and update
+ * their configuration.
+ */
void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
boolean preserveWindows) {
+ ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
+ true /* updateConfiguration */);
+ }
+
+ /**
+ * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
+ */
+ void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+ boolean preserveWindows, boolean updateConfiguration) {
getKeyguardController().beginActivityVisibilityUpdate();
try {
// First the front stacks. In case any are not fullscreen and are in front of home.
@@ -3656,7 +3690,8 @@
final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
- stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows);
+ stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
+ updateConfiguration);
}
}
} finally {