summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Andrii Kulian <akulian@google.com> 2016-09-29 15:25:00 -0700
committer Andrii Kulian <akulian@google.com> 2016-09-29 16:44:38 -0700
commit441e4494682144aec2ec7f19060464af3d29c319 (patch)
treecb11b73a90b6f21d69c3f055a6780327a5d2d849
parent015deed8104aae1f306394cdf66088592995f0da (diff)
Add override and merged config to WindowContainer
This consolidates usages of override and full (merged) configs in WM objects and also adds support of per-display configurations. Having full configs allows us to get current applied config at any level. Test: Manual tests pass. Added some new to WindowContainerTests. Change-Id: I996770433c80da41265f3e14048bd23cead097f9
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java17
-rw-r--r--services/core/java/com/android/server/wm/DockedStackDividerController.java4
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java23
-rw-r--r--services/core/java/com/android/server/wm/Task.java32
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java13
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java114
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java38
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java10
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfacePlacer.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java157
12 files changed, 339 insertions, 83 deletions
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index ba26e13f69c3..c00da8c90cc1 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -729,9 +729,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (mTask.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
// We didn't call prepareFreezingBounds on the task, so use the current value.
- final Configuration config = new Configuration(mService.mGlobalConfiguration);
- config.updateFrom(mTask.mOverrideConfig);
- mFrozenMergedConfig.offer(config);
+ mFrozenMergedConfig.offer(new Configuration(mTask.getConfiguration()));
} else {
mFrozenMergedConfig.offer(new Configuration(mTask.mPreparedFrozenMergedConfig));
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a09c5976e2ec..c4071ab13a6a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -45,6 +45,7 @@ import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import android.annotation.NonNull;
import android.app.ActivityManager.StackId;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region.Op;
@@ -208,18 +209,26 @@ class DisplayContent extends WindowContainer<TaskStack> {
return null;
}
- /** Callback used to notify about configuration changes. */
- void onConfigurationChanged(@NonNull List<Integer> changedStackList) {
+ @Override
+ void onConfigurationChanged(Configuration newParentConfig) {
+ super.onConfigurationChanged(newParentConfig);
+
// The display size information is heavily dependent on the resources in the current
// configuration, so we need to reconfigure it every time the configuration changes.
// See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
mService.reconfigureDisplayLocked(this);
getDockedDividerController().onConfigurationChanged();
+ }
- for (int i = 0; i < mChildren.size(); i++) {
+ /**
+ * Callback used to trigger bounds update after configuration change and get ids of stacks whose
+ * bounds were updated.
+ */
+ void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
final TaskStack stack = mChildren.get(i);
- if (stack.onConfigurationChanged()) {
+ if (stack.updateBoundsAfterConfigChange()) {
changedStackList.add(stack.mStackId);
}
}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index ef8f492f5a6f..15a952dd385e 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -153,7 +153,7 @@ public class DockedStackDividerController implements DimLayerUser {
// If the bounds are fullscreen, return the value of the fullscreen configuration
if (bounds == null || (bounds.left == 0 && bounds.top == 0
&& bounds.right == di.logicalWidth && bounds.bottom == di.logicalHeight)) {
- return mService.mGlobalConfiguration.smallestScreenWidthDp;
+ return mDisplayContent.getConfiguration().smallestScreenWidthDp;
}
final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
@@ -190,7 +190,7 @@ public class DockedStackDividerController implements DimLayerUser {
}
private void initSnapAlgorithmForRotations() {
- final Configuration baseConfig = mService.mGlobalConfiguration;
+ final Configuration baseConfig = mDisplayContent.getConfiguration();
// Initialize the snap algorithms for all 4 screen orientations.
final Configuration config = new Configuration();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 8f533fb1ac61..af5f35ce95bd 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -347,18 +347,35 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
}
}
- int[] onConfigurationChanged(Configuration config) {
+ /** Set new config and return array of ids of stacks that were changed during update. */
+ int[] setGlobalConfigurationIfNeeded(Configuration newConfiguration) {
+ final boolean configChanged = getConfiguration().diff(newConfiguration) != 0;
+ if (!configChanged) {
+ return null;
+ }
+ onConfigurationChanged(newConfiguration);
+ return updateStackBoundsAfterConfigChange();
+ }
+
+ @Override
+ void onConfigurationChanged(Configuration newParentConfig) {
prepareFreezingTaskBounds();
- mService.mGlobalConfiguration = new Configuration(config);
+ super.onConfigurationChanged(newParentConfig);
mService.mPolicy.onConfigurationChanged();
+ }
+ /**
+ * Callback used to trigger bounds update after configuration change and get ids of stacks whose
+ * bounds were updated.
+ */
+ int[] updateStackBoundsAfterConfigChange() {
mChangedStackList.clear();
final int numDisplays = mChildren.size();
for (int i = 0; i < numDisplays; ++i) {
final DisplayContent dc = mChildren.get(i);
- dc.onConfigurationChanged(mChangedStackList);
+ dc.updateStackBoundsAfterConfigChange(mChangedStackList);
}
return mChangedStackList.isEmpty() ? null : ArrayUtils.convertToIntArray(mChangedStackList);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9e8c6091909e..f6598c14da44 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -70,12 +70,6 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
// Whether mBounds is fullscreen
private boolean mFillsParent = true;
- /**
- * Contains configurations settings that are different from the parent configuration due to
- * stack specific operations. E.g. {@link #setBounds}.
- */
- Configuration mOverrideConfig = Configuration.EMPTY;
-
// For comparison with DisplayContent bounds.
private Rect mTmpRect = new Rect();
// For handling display rotations.
@@ -120,8 +114,9 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
}
}
- if (wtoken.mParent != null) {
- wtoken.mParent.removeChild(wtoken);
+ final WindowContainer parent = wtoken.getParent();
+ if (parent != null) {
+ parent.removeChild(wtoken);
}
addChild(wtoken, addPos);
wtoken.mTask = this;
@@ -153,7 +148,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
if (content != null) {
content.mDimLayerController.removeDimLayerUser(this);
}
- mParent.removeChild(this);
+ getParent().removeChild(this);
mService.mTaskIdToTask.delete(mTaskId);
}
@@ -165,7 +160,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
if (DEBUG_STACK) Slog.i(TAG, "moveTaskToStack: removing taskId=" + mTaskId
+ " from stack=" + mStack);
EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask");
- mParent.removeChild(this);
+ getParent().removeChild(this);
stack.addTask(this, toTop);
}
@@ -254,7 +249,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
if (displayContent != null) {
displayContent.mDimLayerController.updateDimLayer(this);
}
- mOverrideConfig = mFillsParent ? Configuration.EMPTY : overrideConfig;
+ onOverrideConfigurationChanged(mFillsParent ? Configuration.EMPTY : overrideConfig);
return boundsChange;
}
@@ -321,8 +316,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
*/
void prepareFreezingBounds() {
mPreparedFrozenBounds.set(mBounds);
- mPreparedFrozenMergedConfig.setTo(mService.mGlobalConfiguration);
- mPreparedFrozenMergedConfig.updateFrom(mOverrideConfig);
+ mPreparedFrozenMergedConfig.setTo(getConfiguration());
}
/**
@@ -334,9 +328,9 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
* bounds's bottom; false if the task's top should be aligned
* the adjusted bounds's top.
*/
- void alignToAdjustedBounds(
- Rect adjustedBounds, Rect tempInsetBounds, boolean alignBottom) {
- if (!isResizeable() || mOverrideConfig == Configuration.EMPTY) {
+ void alignToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds, boolean alignBottom) {
+ final Configuration overrideConfig = getOverrideConfiguration();
+ if (!isResizeable() || Configuration.EMPTY.equals(overrideConfig)) {
return;
}
@@ -348,7 +342,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
}
setTempInsetBounds(tempInsetBounds);
- resizeLocked(mTmpRect2, mOverrideConfig, false /* forced */);
+ resizeLocked(mTmpRect2, overrideConfig, false /* forced */);
}
/** Return true if the current bound can get outputted to the rest of the system as-is. */
@@ -500,12 +494,12 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
mTmpRect2.set(mBounds);
if (!StackId.isTaskResizeAllowed(mStack.mStackId)) {
- setBounds(mTmpRect2, mOverrideConfig);
+ setBounds(mTmpRect2, getOverrideConfiguration());
return;
}
displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
- if (setBounds(mTmpRect2, mOverrideConfig) != BOUNDS_CHANGE_NONE) {
+ if (setBounds(mTmpRect2, getOverrideConfiguration()) != BOUNDS_CHANGE_NONE) {
// Post message to inform activity manager of the bounds change simulating a one-way
// call. We do this to prevent a deadlock between window manager lock and activity
// manager lock been held.
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 21db840ad255..688731256f89 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -478,7 +478,7 @@ class TaskPositioner implements DimLayer.DimLayerUser {
private int getDimSide(int x) {
if (mTask.mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
|| !mTask.mStack.fillsParent()
- || mService.mGlobalConfiguration.orientation != ORIENTATION_LANDSCAPE) {
+ || mTask.mStack.getConfiguration().orientation != ORIENTATION_LANDSCAPE) {
return CTRL_NONE;
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index e374185e7210..179cfd5c6454 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -354,11 +354,8 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
// If the rotation or density didn't match, we'll update it in onConfigurationChanged.
}
- boolean onConfigurationChanged() {
- return updateBoundsAfterConfigChange();
- }
-
- private boolean updateBoundsAfterConfigChange() {
+ /** @return true if bounds were updated to some non-empty value. */
+ boolean updateBoundsAfterConfigChange() {
if (mDisplayContent == null) {
// If the stack is already detached we're not updating anything,
// as it's going away soon anyway.
@@ -459,7 +456,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
// Snap the position to a target.
final int rotation = displayInfo.rotation;
- final int orientation = mService.mGlobalConfiguration.orientation;
+ final int orientation = mDisplayContent.getConfiguration().orientation;
mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
mService.mContext.getResources(), displayWidth, displayHeight,
@@ -713,7 +710,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
di.logicalWidth,
di.logicalHeight,
dockDividerWidth,
- mService.mGlobalConfiguration.orientation == ORIENTATION_PORTRAIT,
+ mDisplayContent.getConfiguration().orientation == ORIENTATION_PORTRAIT,
mTmpRect2).getMiddleTarget().position;
if (dockOnTopOrLeft) {
@@ -1182,7 +1179,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
return DOCKED_INVALID;
}
mDisplayContent.getLogicalDisplayRect(mTmpRect);
- final int orientation = mService.mGlobalConfiguration.orientation;
+ final int orientation = mDisplayContent.getConfiguration().orientation;
return getDockSideUnchecked(bounds, mTmpRect, orientation);
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index af0fbd3ba24a..8777d88a8777 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import android.annotation.CallSuper;
+import android.content.res.Configuration;
import android.view.animation.Animation;
import java.util.Comparator;
@@ -34,13 +35,33 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
*/
class WindowContainer<E extends WindowContainer> implements Comparable<WindowContainer> {
- // The parent of this window container.
- protected WindowContainer mParent = null;
+ /**
+ * The parent of this window container.
+ * For removing or setting new parent {@link #setParent} should be used, because it also
+ * performs configuration updates based on new parent's settings.
+ */
+ private WindowContainer mParent = null;
// List of children for this window container. List is in z-order as the children appear on
// screen with the top-most window container at the tail of the list.
protected final LinkedList<E> mChildren = new LinkedList();
+ /** Contains override configuration settings applied to this window container. */
+ private Configuration mOverrideConfiguration = new Configuration();
+
+ /**
+ * Contains full configuration applied to this window container. Corresponds to full parent's
+ * config with applied {@link #mOverrideConfiguration}.
+ */
+ private Configuration mFullConfiguration = new Configuration();
+
+ /**
+ * Contains merged override configuration settings from the top of the hierarchy down to this
+ * particular instance. It is different from {@link #mFullConfiguration} because it starts from
+ * topmost container's override config instead of global config.
+ */
+ private Configuration mMergedOverrideConfiguration = new Configuration();
+
// The specified orientation for this window container.
protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
@@ -48,6 +69,14 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon
return mParent;
}
+ final protected void setParent(WindowContainer parent) {
+ mParent = parent;
+ // Update full configuration of this container and all its children.
+ onConfigurationChanged(mParent != null ? mParent.mFullConfiguration : Configuration.EMPTY);
+ // Update merged override configuration of this container and all its children.
+ onMergedOverrideConfigurationChanged();
+ }
+
// Temp. holders for a chain of containers we are currently processing.
private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList();
private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList();
@@ -61,12 +90,12 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon
*/
@CallSuper
protected void addChild(E child, Comparator<E> comparator) {
- if (child.mParent != null) {
+ if (child.getParent() != null) {
throw new IllegalArgumentException("addChild: container=" + child.getName()
- + " is already a child of container=" + child.mParent.getName()
+ + " is already a child of container=" + child.getParent().getName()
+ " can't add to container=" + getName());
}
- child.mParent = this;
+ child.setParent(this);
if (mChildren.isEmpty() || comparator == null) {
mChildren.add(child);
@@ -87,12 +116,12 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon
/** Adds the input window container has a child of this container at the input index. */
@CallSuper
protected void addChild(E child, int index) {
- if (child.mParent != null) {
+ if (child.getParent() != null) {
throw new IllegalArgumentException("addChild: container=" + child.getName()
- + " is already a child of container=" + child.mParent.getName()
+ + " is already a child of container=" + child.getParent().getName()
+ " can't add to container=" + getName());
}
- child.mParent = this;
+ child.setParent(this);
mChildren.add(index, child);
}
@@ -104,7 +133,7 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon
@CallSuper
void removeChild(E child) {
if (mChildren.remove(child)) {
- child.mParent = null;
+ child.setParent(null);
} else {
throw new IllegalArgumentException("removeChild: container=" + child.getName()
+ " is not a child of container=" + getName());
@@ -158,6 +187,73 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon
return false;
}
+ /**
+ * Returns full configuration applied to this window container.
+ * This method should be used for getting settings applied in each particular level of the
+ * hierarchy.
+ */
+ Configuration getConfiguration() {
+ return mFullConfiguration;
+ }
+
+ /**
+ * Notify that parent config changed and we need to update full configuration.
+ * @see #mFullConfiguration
+ */
+ void onConfigurationChanged(Configuration newParentConfig) {
+ mFullConfiguration.setTo(newParentConfig);
+ mFullConfiguration.updateFrom(mOverrideConfiguration);
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer child = mChildren.get(i);
+ child.onConfigurationChanged(mFullConfiguration);
+ }
+ }
+
+ /** Returns override configuration applied to this window container. */
+ Configuration getOverrideConfiguration() {
+ return mOverrideConfiguration;
+ }
+
+ /**
+ * Update override configuration and recalculate full config.
+ * @see #mOverrideConfiguration
+ * @see #mFullConfiguration
+ */
+ void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ mOverrideConfiguration.setTo(overrideConfiguration);
+ // Update full configuration of this container and all its children.
+ onConfigurationChanged(mParent != null ? mParent.getConfiguration() : Configuration.EMPTY);
+ // Update merged override config of this container and all its children.
+ onMergedOverrideConfigurationChanged();
+ }
+
+ /**
+ * Get merged override configuration from the top of the hierarchy down to this
+ * particular instance. This should be reported to client as override config.
+ */
+ Configuration getMergedOverrideConfiguration() {
+ return mMergedOverrideConfiguration;
+ }
+
+ /**
+ * Update merged override configuration based on corresponding parent's config and notify all
+ * its children. If there is no parent, merged override configuration will set equal to current
+ * override config.
+ * @see #mMergedOverrideConfiguration
+ */
+ private void onMergedOverrideConfigurationChanged() {
+ if (mParent != null) {
+ mMergedOverrideConfiguration.setTo(mParent.getMergedOverrideConfiguration());
+ mMergedOverrideConfiguration.updateFrom(mOverrideConfiguration);
+ } else {
+ mMergedOverrideConfiguration.setTo(mOverrideConfiguration);
+ }
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer child = mChildren.get(i);
+ child.onMergedOverrideConfigurationChanged();
+ }
+ }
+
void setWaitingForDrawnIfResizingChanged() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer wc = mChildren.get(i);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1ed4055746b8..b9f3d5ac047e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -592,12 +592,6 @@ public class WindowManagerService extends IWindowManager.Stub
// State while inside of layoutAndPlaceSurfacesLocked().
boolean mFocusMayChange;
- /**
- * Current global configuration information. Contains general settings for the entire system,
- * corresponds to the configuration of the default display.
- */
- Configuration mGlobalConfiguration = new Configuration();
-
// This is held as long as we have the screen frozen, to give us time to
// perform a rotation animation when turning off shows the lock screen which
// changes the orientation.
@@ -2674,7 +2668,8 @@ public class WindowManagerService extends IWindowManager.Stub
// is running.
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
if (okToDisplay()) {
- DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
+ final DisplayContent displayContent = atoken.mTask.getDisplayContent();
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
final int width = displayInfo.appWidth;
final int height = displayInfo.appHeight;
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG_WM,
@@ -2711,10 +2706,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "Loading animation for app transition."
+ " transit=" + AppTransition.appTransitionToString(transit) + " enter=" + enter
+ " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
- Animation a = mAppTransition.loadAnimation(lp, transit, enter,
- mGlobalConfiguration.uiMode, mGlobalConfiguration.orientation, frame,
- displayFrame, insets, surfaceInsets, isVoiceInteraction, freeform,
- atoken.mTask.mTaskId);
+ final Configuration displayConfig = displayContent.getConfiguration();
+ Animation a = mAppTransition.loadAnimation(lp, transit, enter, displayConfig.uiMode,
+ displayConfig.orientation, frame, displayFrame, insets, surfaceInsets,
+ isVoiceInteraction, freeform, atoken.mTask.mTaskId);
if (a != null) {
if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
final int containingWidth = frame.width();
@@ -3104,11 +3099,7 @@ public class WindowManagerService extends IWindowManager.Stub
mWaitingForConfig = false;
mLastFinishedFreezeSource = "new-config";
}
- final boolean configChanged = mGlobalConfiguration.diff(config) != 0;
- if (!configChanged) {
- return null;
- }
- return mRoot.onConfigurationChanged(config);
+ return mRoot.setGlobalConfigurationIfNeeded(config);
}
}
@@ -5595,7 +5586,7 @@ public class WindowManagerService extends IWindowManager.Stub
// the top of the method, the caller is obligated to call computeNewConfigurationLocked().
// By updating the Display info here it will be available to
// computeScreenConfigurationLocked later.
- updateDisplayAndOrientationLocked(mGlobalConfiguration.uiMode);
+ updateDisplayAndOrientationLocked(mRoot.getConfiguration().uiMode);
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (!inTransaction) {
@@ -6961,8 +6952,8 @@ public class WindowManagerService extends IWindowManager.Stub
View view = null;
try {
- final Configuration overrideConfig = wtoken != null && wtoken.mTask != null
- ? wtoken.mTask.mOverrideConfig : null;
+ final Configuration overrideConfig =
+ wtoken != null ? wtoken.getMergedOverrideConfiguration() : null;
view = mPolicy.addStartingWindow(wtoken.token, sd.pkg, sd.theme,
sd.compatInfo, sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo,
sd.windowFlags, overrideConfig);
@@ -7911,9 +7902,10 @@ public class WindowManagerService extends IWindowManager.Stub
displayContent.layoutNeeded = true;
boolean configChanged = updateOrientationFromAppTokensLocked(false);
- mTempConfiguration.setTo(mGlobalConfiguration);
+ final Configuration globalConfig = mRoot.getConfiguration();
+ mTempConfiguration.setTo(globalConfig);
computeScreenConfigurationLocked(mTempConfiguration);
- configChanged |= mGlobalConfiguration.diff(mTempConfiguration) != 0;
+ configChanged |= globalConfig.diff(mTempConfiguration) != 0;
if (configChanged) {
mWaitingForConfig = true;
@@ -8071,7 +8063,7 @@ public class WindowManagerService extends IWindowManager.Stub
w.setReportResizeHints();
boolean configChanged = w.isConfigChanged();
if (DEBUG_CONFIGURATION && configChanged) {
- Slog.v(TAG_WM, "Win " + w + " config changed: " + mGlobalConfiguration);
+ Slog.v(TAG_WM, "Win " + w + " config changed: " + w.getConfiguration());
}
final boolean dragResizingChanged = w.isDragResizeChanged()
&& !w.isDragResizingChangeReported();
@@ -8959,7 +8951,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
pw.println();
- pw.print(" mGlobalConfiguration="); pw.println(mGlobalConfiguration);
+ pw.print(" mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad);
pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
if (mLastFocus != mCurrentFocus) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c3affeb9a25c..df099dcb3aea 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2886,14 +2886,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
outConfig.setTo(mAppToken.mFrozenMergedConfig.peek());
return;
}
- final Task task = getTask();
- final Configuration overrideConfig = task != null
- ? task.mOverrideConfig
- : Configuration.EMPTY;
- outConfig.setTo(mService.mGlobalConfiguration);
- if (overrideConfig != Configuration.EMPTY) {
- outConfig.updateFrom(overrideConfig);
- }
+ outConfig.setTo(
+ mAppToken != null ? getConfiguration() : mDisplayContent.getConfiguration());
}
void reportResized() {
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 6d10c5aaf34e..d1439f307df7 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -25,6 +25,7 @@ import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
+import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
@@ -233,7 +234,7 @@ class WindowSurfacePlacer {
}
mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation,
- mService.mGlobalConfiguration.uiMode);
+ displayContent.getConfiguration().uiMode);
if (isDefaultDisplay) {
// Not needed on non-default displays.
mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
@@ -840,13 +841,14 @@ class WindowSurfacePlacer {
Rect appRect = win != null ? win.getContentFrameLw() :
new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
Rect insets = win != null ? win.mContentInsets : null;
+ final Configuration displayConfig = displayContent.getConfiguration();
// For the new aspect-scaled transition, we want it to always show
// above the animating opening/closing window, and we want to
// synchronize its thumbnail surface with the surface for the
// open/close animation (only on the way down)
anim = mService.mAppTransition.createThumbnailAspectScaleAnimationLocked(appRect,
- insets, thumbnailHeader, taskId, mService.mGlobalConfiguration.uiMode,
- mService.mGlobalConfiguration.orientation);
+ insets, thumbnailHeader, taskId, displayConfig.uiMode,
+ displayConfig.orientation);
openingAppAnimator.thumbnailForceAboveLayer = Math.max(openingLayer, closingLayer);
openingAppAnimator.deferThumbnailDestruction =
!mService.mAppTransition.isNextThumbnailTransitionScaleUp();
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index eb2372a03a96..6eb347ba7444 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import org.junit.Test;
import org.junit.runner.RunWith;
+import android.content.res.Configuration;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -28,6 +29,8 @@ import java.util.Comparator;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static org.junit.Assert.assertEquals;
@@ -377,6 +380,160 @@ public class WindowContainerTests {
assertEquals(1, child2223.compareTo(child21));
}
+ @Test
+ public void testConfigurationInit() throws Exception {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+
+ // Check root container initial config.
+ final TestWindowContainer root = builder.setLayer(0).build();
+ assertEquals(Configuration.EMPTY, root.getOverrideConfiguration());
+ assertEquals(Configuration.EMPTY, root.getMergedOverrideConfiguration());
+ assertEquals(Configuration.EMPTY, root.getConfiguration());
+
+ // Check child initial config.
+ final TestWindowContainer child1 = root.addChildWindow();
+ assertEquals(Configuration.EMPTY, child1.getOverrideConfiguration());
+ assertEquals(Configuration.EMPTY, child1.getMergedOverrideConfiguration());
+ assertEquals(Configuration.EMPTY, child1.getConfiguration());
+
+ // Check child initial config if root has overrides.
+ final Configuration rootOverrideConfig = new Configuration();
+ rootOverrideConfig.fontScale = 1.3f;
+ root.onOverrideConfigurationChanged(rootOverrideConfig);
+ final TestWindowContainer child2 = root.addChildWindow();
+ assertEquals(Configuration.EMPTY, child2.getOverrideConfiguration());
+ assertEquals(rootOverrideConfig, child2.getMergedOverrideConfiguration());
+ assertEquals(rootOverrideConfig, child2.getConfiguration());
+
+ // Check child initial config if root has parent config set.
+ final Configuration rootParentConfig = new Configuration();
+ rootParentConfig.fontScale = 0.8f;
+ rootParentConfig.orientation = SCREEN_ORIENTATION_LANDSCAPE;
+ root.onConfigurationChanged(rootParentConfig);
+ final Configuration rootFullConfig = new Configuration(rootParentConfig);
+ rootFullConfig.updateFrom(rootOverrideConfig);
+
+ final TestWindowContainer child3 = root.addChildWindow();
+ assertEquals(Configuration.EMPTY, child3.getOverrideConfiguration());
+ assertEquals(rootOverrideConfig, child3.getMergedOverrideConfiguration());
+ assertEquals(rootFullConfig, child3.getConfiguration());
+ }
+
+ @Test
+ public void testConfigurationChangeOnAddRemove() throws Exception {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+
+ // Init root's config.
+ final TestWindowContainer root = builder.setLayer(0).build();
+ final Configuration rootOverrideConfig = new Configuration();
+ rootOverrideConfig.fontScale = 1.3f;
+ root.onOverrideConfigurationChanged(rootOverrideConfig);
+
+ // Init child's config.
+ final TestWindowContainer child = root.addChildWindow();
+ final Configuration childOverrideConfig = new Configuration();
+ childOverrideConfig.densityDpi = 320;
+ child.onOverrideConfigurationChanged(childOverrideConfig);
+
+ // Check configuration update when child is removed from parent.
+ root.removeChild(child);
+ assertEquals(childOverrideConfig, child.getOverrideConfiguration());
+ assertEquals(childOverrideConfig, child.getMergedOverrideConfiguration());
+ assertEquals(childOverrideConfig, child.getConfiguration());
+
+ // It may be paranoia... but let's check if parent's config didn't change after removal.
+ assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+ assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
+ assertEquals(rootOverrideConfig, root.getConfiguration());
+
+ // Check configuration update when child is added to parent.
+ final Configuration mergedOverrideConfig = new Configuration(root.getConfiguration());
+ mergedOverrideConfig.updateFrom(childOverrideConfig);
+ root.addChildWindow(child);
+ assertEquals(childOverrideConfig, child.getOverrideConfiguration());
+ assertEquals(mergedOverrideConfig, child.getMergedOverrideConfiguration());
+ assertEquals(mergedOverrideConfig, child.getConfiguration());
+ }
+
+ @Test
+ public void testConfigurationChangePropagation() throws Exception {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+
+ // Builds 3-level vertical hierarchy with one window container on each level.
+ // In addition to different overrides on each level, everyone in hierarchy will have one
+ // common overridden value - orientation;
+
+ // Init root's config.
+ final TestWindowContainer root = builder.setLayer(0).build();
+ final Configuration rootOverrideConfig = new Configuration();
+ rootOverrideConfig.fontScale = 1.3f;
+ rootOverrideConfig.orientation = SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+ root.onOverrideConfigurationChanged(rootOverrideConfig);
+
+ // Init children.
+ final TestWindowContainer child1 = root.addChildWindow();
+ final Configuration childOverrideConfig1 = new Configuration();
+ childOverrideConfig1.densityDpi = 320;
+ childOverrideConfig1.orientation = SCREEN_ORIENTATION_LANDSCAPE;
+ child1.onOverrideConfigurationChanged(childOverrideConfig1);
+
+ final TestWindowContainer child2 = child1.addChildWindow();
+ final Configuration childOverrideConfig2 = new Configuration();
+ childOverrideConfig2.screenWidthDp = 150;
+ childOverrideConfig2.orientation = SCREEN_ORIENTATION_PORTRAIT;
+ child2.onOverrideConfigurationChanged(childOverrideConfig2);
+
+ // Check configuration on all levels when root override is updated.
+ rootOverrideConfig.smallestScreenWidthDp = 200;
+ root.onOverrideConfigurationChanged(rootOverrideConfig);
+
+ final Configuration mergedOverrideConfig1 = new Configuration(rootOverrideConfig);
+ mergedOverrideConfig1.updateFrom(childOverrideConfig1);
+ final Configuration mergedConfig1 = new Configuration(mergedOverrideConfig1);
+
+ final Configuration mergedOverrideConfig2 = new Configuration(mergedOverrideConfig1);
+ mergedOverrideConfig2.updateFrom(childOverrideConfig2);
+ final Configuration mergedConfig2 = new Configuration(mergedOverrideConfig2);
+
+ assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+ assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
+ assertEquals(rootOverrideConfig, root.getConfiguration());
+
+ assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
+ assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
+ assertEquals(mergedConfig1, child1.getConfiguration());
+
+ assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
+ assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
+ assertEquals(mergedConfig2, child2.getConfiguration());
+
+ // Check configuration on all levels when root parent config is updated.
+ final Configuration rootParentConfig = new Configuration();
+ rootParentConfig.screenHeightDp = 100;
+ rootParentConfig.orientation = SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+ root.onConfigurationChanged(rootParentConfig);
+ final Configuration mergedRootConfig = new Configuration(rootParentConfig);
+ mergedRootConfig.updateFrom(rootOverrideConfig);
+
+ mergedConfig1.setTo(mergedRootConfig);
+ mergedConfig1.updateFrom(mergedOverrideConfig1);
+
+ mergedConfig2.setTo(mergedConfig1);
+ mergedConfig2.updateFrom(mergedOverrideConfig2);
+
+ assertEquals(rootOverrideConfig, root.getOverrideConfiguration());
+ assertEquals(rootOverrideConfig, root.getMergedOverrideConfiguration());
+ assertEquals(mergedRootConfig, root.getConfiguration());
+
+ assertEquals(childOverrideConfig1, child1.getOverrideConfiguration());
+ assertEquals(mergedOverrideConfig1, child1.getMergedOverrideConfiguration());
+ assertEquals(mergedConfig1, child1.getConfiguration());
+
+ assertEquals(childOverrideConfig2, child2.getOverrideConfiguration());
+ assertEquals(mergedOverrideConfig2, child2.getMergedOverrideConfiguration());
+ assertEquals(mergedConfig2, child2.getConfiguration());
+ }
+
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
private class TestWindowContainer extends WindowContainer<TestWindowContainer> {
private final int mLayer;