Also freeze configuration when freezing bounds
We also need to freeze the override configuration so we don't report
the new configuration too early, which leads to bugs.
Bug: 27915587
Change-Id: Idffadbb02ab0311796caa760ae1f467fd2d17768
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index abbb5f4..b773a4e 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -34,6 +34,7 @@
import android.annotation.NonNull;
import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Message;
import android.os.RemoteException;
@@ -133,6 +134,7 @@
int mPendingRelaunchCount;
ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
+ ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
AppWindowToken(WindowManagerService _service, IApplicationToken _token,
boolean _voiceInteraction) {
@@ -675,6 +677,16 @@
*/
private void freezeBounds() {
mFrozenBounds.offer(new Rect(mTask.mPreparedFrozenBounds));
+
+ if (mTask.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
+ // We didn't call prepareFreezingBounds on the task, so use the current value.
+ final Configuration config = new Configuration(service.mCurConfiguration);
+ config.updateFrom(mTask.mOverrideConfig);
+ mFrozenMergedConfig.offer(config);
+ } else {
+ mFrozenMergedConfig.offer(new Configuration(mTask.mPreparedFrozenMergedConfig));
+ }
+ mTask.mPreparedFrozenMergedConfig.setToDefaults();
}
/**
@@ -682,6 +694,7 @@
*/
private void unfreezeBounds() {
mFrozenBounds.remove();
+ mFrozenMergedConfig.remove();
for (int i = windows.size() - 1; i >= 0; i--) {
final WindowState win = windows.get(i);
if (!win.mHasSurface) {
@@ -747,6 +760,7 @@
}
if (!mFrozenBounds.isEmpty()) {
pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
+ pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
}
if (mPendingRelaunchCount != 0) {
pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 8f4197f..0d35354 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -62,6 +62,7 @@
// Content limits relative to the DisplayContent this sits in.
private Rect mBounds = new Rect();
final Rect mPreparedFrozenBounds = new Rect();
+ final Configuration mPreparedFrozenMergedConfig = new Configuration();
private Rect mPreScrollBounds = new Rect();
private boolean mScrollValid;
@@ -77,7 +78,7 @@
// Contains configurations settings that are different from the global configuration due to
// stack specific operations. E.g. {@link #setBounds}.
- Configuration mOverrideConfig;
+ Configuration mOverrideConfig = Configuration.EMPTY;
// For comparison with DisplayContent bounds.
private Rect mTmpRect = new Rect();
@@ -320,6 +321,8 @@
*/
void prepareFreezingBounds() {
mPreparedFrozenBounds.set(mBounds);
+ mPreparedFrozenMergedConfig.setTo(mService.mCurConfiguration);
+ mPreparedFrozenMergedConfig.updateFrom(mOverrideConfig);
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 09428b1..1132758 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3737,6 +3737,7 @@
if (!configChanged) {
return null;
}
+ prepareFreezingAllTaskBounds();
mCurConfiguration = new Configuration(config);
return onConfigurationChanged();
}
@@ -3752,6 +3753,16 @@
}
}
+ private void prepareFreezingAllTaskBounds() {
+ for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
+ ArrayList<TaskStack> stacks = mDisplayContents.valueAt(i).getStacks();
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final TaskStack stack = stacks.get(stackNdx);
+ stack.prepareFreezingTaskBounds();
+ }
+ }
+
+ }
private int[] onConfigurationChanged() {
mPolicy.onConfigurationChanged();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c9d945a..c3f2367 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -190,8 +190,7 @@
int mLayoutSeq = -1;
- private Configuration mConfiguration = Configuration.EMPTY;
- private Configuration mOverrideConfig = Configuration.EMPTY;
+ private final Configuration mTmpConfig = new Configuration();
// Represents the changes from our override configuration applied
// to the global configuration. This is the only form of configuration
// which is suitable for delivery to the client.
@@ -1417,13 +1416,12 @@
}
boolean isConfigChanged() {
- final Task task = getTask();
- final Configuration overrideConfig =
- (task != null) ? task.mOverrideConfig : Configuration.EMPTY;
- final Configuration serviceConfig = mService.mCurConfiguration;
- boolean configChanged =
- (mConfiguration != serviceConfig && mConfiguration.diff(serviceConfig) != 0)
- || (mOverrideConfig != overrideConfig && !mOverrideConfig.equals(overrideConfig));
+ getMergedConfig(mTmpConfig);
+
+ // If the merged configuration is still empty, it means that we haven't issues the
+ // configuration to the client yet and we need to return true so the configuration updates.
+ boolean configChanged = mMergedConfiguration.equals(Configuration.EMPTY)
+ || mTmpConfig.diff(mMergedConfiguration) != 0;
if ((mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
// Retain configuration changed status until resetConfiguration called.
@@ -1457,18 +1455,6 @@
}
}
- private void setConfiguration(
- final Configuration newConfig, final Configuration newOverrideConfig) {
- mConfiguration = newConfig;
- mOverrideConfig = newOverrideConfig;
- mConfigHasChanged = false;
-
- mMergedConfiguration.setTo(newConfig);
- if (newOverrideConfig != null && newOverrideConfig != Configuration.EMPTY) {
- mMergedConfiguration.updateFrom(newOverrideConfig);
- }
- }
-
void setHasSurface(boolean hasSurface) {
mHasSurface = hasSurface;
}
@@ -2266,18 +2252,32 @@
* @return A configuration suitable for sending to the client.
*/
private Configuration updateConfiguration() {
- final Task task = getTask();
- final Configuration overrideConfig =
- (task != null) ? task.mOverrideConfig : Configuration.EMPTY;
final boolean configChanged = isConfigChanged();
+ getMergedConfig(mMergedConfiguration);
+ mConfigHasChanged = false;
if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) {
Slog.i(TAG, "Sending new config to window " + this + ": " +
- " / config=" + mService.mCurConfiguration + " overrideConfig=" + overrideConfig);
+ " / mergedConfig=" + mMergedConfiguration);
}
- setConfiguration(mService.mCurConfiguration, overrideConfig);
return mMergedConfiguration;
}
+ private void getMergedConfig(Configuration outConfig) {
+ if (mAppToken != null && mAppToken.mFrozenMergedConfig.size() > 0) {
+ outConfig.setTo(mAppToken.mFrozenMergedConfig.peek());
+ return;
+ }
+ final Task task = getTask();
+ final Configuration overrideConfig = task != null
+ ? task.mOverrideConfig
+ : Configuration.EMPTY;
+ final Configuration serviceConfig = mService.mCurConfiguration;
+ outConfig.setTo(serviceConfig);
+ if (overrideConfig != Configuration.EMPTY) {
+ outConfig.updateFrom(overrideConfig);
+ }
+ }
+
void reportResized() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
try {
@@ -2572,10 +2572,7 @@
getTouchableRegion(region);
pw.print(prefix); pw.print("touchable region="); pw.println(region);
}
- pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
- if (mOverrideConfig != Configuration.EMPTY) {
- pw.print(prefix); pw.print("mOverrideConfig="); pw.println(mOverrideConfig);
- }
+ pw.print(prefix); pw.print("mMergedConfiguration="); pw.println(mMergedConfiguration);
}
pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
pw.print(" mShownPosition="); mShownPosition.printShortString(pw);