Merge "Reducing number of configuration changes during PiP transition."
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 1b19382..082b6b5 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -22,7 +22,6 @@
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -47,7 +46,6 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
import static android.os.Build.VERSION_CODES.HONEYCOMB;
import static android.os.Build.VERSION_CODES.O;
@@ -85,7 +83,6 @@
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
-import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.IBinder;
@@ -290,8 +287,8 @@
/**
* Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
*/
- private final Configuration mTmpGlobalConfig = new Configuration();
- private final Configuration mTmpTaskConfig = new Configuration();
+ private final Configuration mTmpConfig1 = new Configuration();
+ private final Configuration mTmpConfig2 = new Configuration();
private static String startingWindowStateToString(int state) {
switch (state) {
@@ -1975,13 +1972,13 @@
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Ensuring correct configuration: " + this);
- // Short circuit: if the two configurations are equal (the common case), then there is
- // nothing to do.
- final Configuration newGlobalConfig = service.getGlobalConfiguration();
- final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
- if (mLastReportedConfiguration.equals(newGlobalConfig)
- && mLastReportedOverrideConfiguration.equals(newTaskMergedOverrideConfig)
- && !forceNewConfig) {
+ // Short circuit: if the two full configurations are equal (the common case), then there is
+ // nothing to do. We test the full configuration instead of the global and merged override
+ // configurations because there are cases (like moving a task to the pinned stack) where
+ // the combine configurations are equal, but would otherwise differ in the override config
+ mTmpConfig1.setTo(mLastReportedConfiguration);
+ mTmpConfig1.updateFrom(mLastReportedOverrideConfiguration);
+ if (task.getConfiguration().equals(mTmpConfig1) && !forceNewConfig) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Configuration unchanged in " + this);
return true;
@@ -1997,14 +1994,16 @@
// Okay we now are going to make this activity have the new config.
// But then we need to figure out how it needs to deal with that.
- mTmpGlobalConfig.setTo(mLastReportedConfiguration);
- mTmpTaskConfig.setTo(mLastReportedOverrideConfiguration);
+ final Configuration newGlobalConfig = service.getGlobalConfiguration();
+ final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
+ mTmpConfig1.setTo(mLastReportedConfiguration);
+ mTmpConfig2.setTo(mLastReportedOverrideConfiguration);
mLastReportedConfiguration.setTo(newGlobalConfig);
mLastReportedOverrideConfiguration.setTo(newTaskMergedOverrideConfig);
int taskChanges = getTaskConfigurationChanges(this, newTaskMergedOverrideConfig,
- mTmpTaskConfig);
- final int changes = mTmpGlobalConfig.diff(newGlobalConfig) | taskChanges;
+ mTmpConfig2);
+ final int changes = mTmpConfig1.diff(newGlobalConfig) | taskChanges;
if (changes == 0 && !forceNewConfig) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Configuration no differences in " + this);
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 520d4ee..f8645d6 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -35,7 +35,6 @@
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
-import android.graphics.GraphicBuffer;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Debug;
@@ -52,6 +51,7 @@
import com.android.internal.util.XmlUtils;
import com.android.server.wm.AppWindowContainerController;
+import com.android.server.wm.StackWindowController;
import com.android.server.wm.TaskWindowContainerController;
import com.android.server.wm.TaskWindowContainerListener;
@@ -278,7 +278,6 @@
private final Rect mTmpStableBounds = new Rect();
private final Rect mTmpNonDecorBounds = new Rect();
private final Rect mTmpRect = new Rect();
- private final Rect mTmpRect2 = new Rect();
// Last non-fullscreen bounds the task was launched in or resized to.
// The information is persisted and used to determine the appropriate stack to launch the
@@ -1838,66 +1837,38 @@
return !mTmpConfig.equals(newConfig);
}
- private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds,
- boolean overrideWidth, boolean overrideHeight) {
- mTmpRect2.set(inInsetBounds);
- mService.mWindowManager.subtractNonDecorInsets(mTmpRect2);
- int leftInset = mTmpRect2.left - inInsetBounds.left;
- int topInset = mTmpRect2.top - inInsetBounds.top;
- int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
- int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
- inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
- }
-
- private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds,
- boolean overrideWidth, boolean overrideHeight) {
- mTmpRect2.set(inInsetBounds);
- mService.mWindowManager.subtractStableInsets(mTmpRect2);
- int leftInset = mTmpRect2.left - inInsetBounds.left;
- int topInset = mTmpRect2.top - inInsetBounds.top;
- int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
- int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
- inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
- }
-
/** Clears passed config and fills it with new override values. */
private void calculateOverrideConfig(Configuration config, Rect bounds, Rect insetBounds,
boolean overrideWidth, boolean overrideHeight) {
mTmpNonDecorBounds.set(bounds);
mTmpStableBounds.set(bounds);
- final Configuration parentConfig = getParent().getConfiguration();
config.unset();
+ final Configuration parentConfig = getParent().getConfiguration();
final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
- final boolean isFloatingTask = mStack != null && StackId.tasksAreFloating(mStack.mStackId);
- if (isFloatingTask) {
- // Floating tasks should not be resized to the screen's bounds.
- config.screenWidthDp = (int) (mTmpStableBounds.width() / density);
- config.screenHeightDp = (int) (mTmpStableBounds.height() / density);
- } else {
- // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen area,
- // i.e. the screen area without the system bars.
- // Additionally task dimensions should not be bigger than its parents dimensions.
- subtractNonDecorInsets(mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds,
- overrideWidth, overrideHeight);
- subtractStableInsets(mTmpStableBounds, insetBounds != null ? insetBounds : bounds,
- overrideWidth, overrideHeight);
- config.screenWidthDp = Math.min(
- (int) (mTmpStableBounds.width() / density), parentConfig.screenWidthDp);
- config.screenHeightDp = Math.min(
- (int) (mTmpStableBounds.height() / density), parentConfig.screenHeightDp);
- }
// TODO: Orientation?
config.orientation = (config.screenWidthDp <= config.screenHeightDp)
? Configuration.ORIENTATION_PORTRAIT
: Configuration.ORIENTATION_LANDSCAPE;
+ if (mStack != null) {
+ final StackWindowController stackController = mStack.getWindowContainerController();
+ stackController.adjustConfigurationForBounds(bounds, insetBounds,
+ mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
+ config, parentConfig);
+ } else {
+ // No stack, give some default values
+ config.smallestScreenWidthDp =
+ mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
+ config.screenWidthDp = config.screenHeightDp = config.smallestScreenWidthDp;
+ Slog.wtf(TAG, "Expected stack when caclulating override config");
+ }
// For calculating screen layout, we need to use the non-decor inset screen area for the
// calculation for compatibility reasons, i.e. screen area without system bars that could
// never go away in Honeycomb.
- final int compatScreenWidthDp = (int)(mTmpNonDecorBounds.width() / density);
- final int compatScreenHeightDp = (int)(mTmpNonDecorBounds.height() / density);
+ final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
+ final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
// We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
// calculation with partial default.
final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
@@ -1905,8 +1876,6 @@
final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
- config.smallestScreenWidthDp = mService.mWindowManager.getSmallestWidthForTaskBounds(
- insetBounds != null ? insetBounds : bounds);
}
/**
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 0a92a81..75a79fd 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -152,11 +152,6 @@
int getSmallestWidthDpForBounds(Rect bounds) {
final DisplayInfo di = mDisplayContent.getDisplayInfo();
- // 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 mDisplayContent.getConfiguration().smallestScreenWidthDp;
- }
final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
int minWidth = Integer.MAX_VALUE;
@@ -185,7 +180,7 @@
mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
mService.mPolicy.getStableInsetsLw(rotation, mTmpRect2.width(), mTmpRect2.height(),
mTmpRect3);
- mService.subtractInsets(mTmpRect2, mTmpRect3, mTmpRect);
+ mService.intersectDisplayInsetBounds(mTmpRect2, mTmpRect3, mTmpRect);
minWidth = Math.min(mTmpRect.width(), minWidth);
}
return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 36d07e0..142f69a 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+
+import android.app.ActivityManager.StackId;
import android.app.RemoteAction;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -24,6 +27,8 @@
import android.os.Message;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.DisplayInfo;
+
import com.android.server.UiThread;
import com.android.internal.annotations.VisibleForTesting;
@@ -48,6 +53,12 @@
private final H mHandler;
+ // Temp bounds only used in adjustConfigurationForBounds()
+ private final Rect mTmpRect = new Rect();
+ private final Rect mTmpStableInsets = new Rect();
+ private final Rect mTmpNonDecorInsets = new Rect();
+ private final Rect mTmpDisplayBounds = new Rect();
+
public StackWindowController(int stackId, StackWindowListener listener,
int displayId, boolean onTop, Rect outBounds) {
this(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
@@ -289,6 +300,107 @@
}
}
+ /**
+ * Adjusts the screen size in dp's for the {@param config} for the given params.
+ */
+ public void adjustConfigurationForBounds(Rect bounds, Rect insetBounds,
+ Rect nonDecorBounds, Rect stableBounds, boolean overrideWidth,
+ boolean overrideHeight, float density, Configuration config,
+ Configuration parentConfig) {
+ synchronized (mWindowMap) {
+ final TaskStack stack = mContainer;
+ final DisplayContent displayContent = stack.getDisplayContent();
+ final DisplayInfo di = displayContent.getDisplayInfo();
+
+ // Get the insets and display bounds
+ mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+ mTmpStableInsets);
+ mService.mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+ mTmpNonDecorInsets);
+ mTmpDisplayBounds.set(0, 0, di.logicalWidth, di.logicalHeight);
+
+ int width;
+ int height;
+ if (StackId.tasksAreFloating(mStackId)) {
+ // Floating tasks should not be resized to the screen's bounds.
+
+ if (bounds.width() == mTmpDisplayBounds.width() &&
+ bounds.height() == mTmpDisplayBounds.height()) {
+ // If the bounds we are animating is the same as the fullscreen stack
+ // dimensions, then apply the same inset calculations that we normally do for
+ // the fullscreen stack, without intersecting it with the display bounds
+ stableBounds.inset(mTmpStableInsets);
+ nonDecorBounds.inset(mTmpNonDecorInsets);
+ }
+ width = (int) (stableBounds.width() / density);
+ height = (int) (stableBounds.height() / density);
+ } else {
+ // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
+ // area, i.e. the screen area without the system bars.
+ // Additionally task dimensions should not be bigger than its parents dimensions.
+ // The non decor inset are areas that could never be removed in Honeycomb. See
+ // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
+ intersectDisplayBoundsExcludeInsets(nonDecorBounds,
+ insetBounds != null ? insetBounds : bounds, mTmpNonDecorInsets,
+ mTmpDisplayBounds, overrideWidth, overrideHeight);
+ intersectDisplayBoundsExcludeInsets(stableBounds,
+ insetBounds != null ? insetBounds : bounds, mTmpStableInsets,
+ mTmpDisplayBounds, overrideWidth, overrideHeight);
+ width = Math.min((int) (stableBounds.width() / density),
+ parentConfig.screenWidthDp);
+ height = Math.min((int) (stableBounds.height() / density),
+ parentConfig.screenHeightDp);
+ }
+
+ config.screenWidthDp = width;
+ config.screenHeightDp = height;
+ config.smallestScreenWidthDp = getSmallestWidthForTaskBounds(
+ insetBounds != null ? insetBounds : bounds, density);
+ }
+ }
+
+ /**
+ * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
+ * inset areas.
+ *
+ * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
+ */
+ private void intersectDisplayBoundsExcludeInsets(Rect inOutBounds, Rect inInsetBounds,
+ Rect stableInsets, Rect displayBounds, boolean overrideWidth, boolean overrideHeight) {
+ mTmpRect.set(inInsetBounds);
+ mService.intersectDisplayInsetBounds(displayBounds, stableInsets, mTmpRect);
+ int leftInset = mTmpRect.left - inInsetBounds.left;
+ int topInset = mTmpRect.top - inInsetBounds.top;
+ int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect.right;
+ int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect.bottom;
+ inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
+ }
+
+ /**
+ * Calculates the smallest width for a task given the {@param bounds}.
+ *
+ * @return the smallest width to be used in the Configuration, in dips
+ */
+ private int getSmallestWidthForTaskBounds(Rect bounds, float density) {
+ final DisplayContent displayContent = mContainer.getDisplayContent();
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+
+ if (bounds == null || (bounds.width() == displayInfo.logicalWidth &&
+ bounds.height() == displayInfo.logicalHeight)) {
+ // If the bounds are fullscreen, return the value of the fullscreen configuration
+ return displayContent.getConfiguration().smallestScreenWidthDp;
+ } else if (StackId.tasksAreFloating(mStackId)) {
+ // For floating tasks, calculate the smallest width from the bounds of the task
+ return (int) (Math.min(bounds.width(), bounds.height()) / density);
+ } else {
+ // Iterating across all screen orientations, and return the minimum of the task
+ // width taking into account that the bounds might change because the snap algorithm
+ // snaps to a different value
+ return displayContent.getDockedDividerController()
+ .getSmallestWidthDpForBounds(bounds);
+ }
+ }
+
void requestResize(Rect bounds) {
mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b09d699..b9429f4 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1476,7 +1476,10 @@
@Override
public void getFullScreenBounds(Rect bounds) {
- getDisplayContent().getContentRect(bounds);
+ // This is currently only used for the pinned stack animation when leaving PiP
+ // (see {@link BoundsAnimationController}), and in that case we need to animate this back
+ // to the full bounds to match the fullscreen stack
+ getDisplayContent().getLogicalDisplayRect(bounds);
}
public boolean hasMovementAnimations() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 122db7e..ad8fb8c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7544,63 +7544,12 @@
}
}
- private void getNonDecorInsetsLocked(Rect outInsets) {
- final DisplayInfo di = getDefaultDisplayInfoLocked();
- mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
- }
-
- /**
- * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
- * inset areas.
- *
- * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
- */
- public void subtractStableInsets(Rect inOutBounds) {
- synchronized (mWindowMap) {
- getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect2);
- final DisplayInfo di = getDefaultDisplayInfoLocked();
- mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
- subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
- }
- }
-
- /**
- * Intersects the specified {@code inOutBounds} with the display frame that excludes
- * areas that could never be removed in Honeycomb. See
- * {@link WindowManagerPolicy#getNonDecorInsetsLw}.
- *
- * @param inOutBounds The inOutBounds to subtract the inset areas from.
- */
- public void subtractNonDecorInsets(Rect inOutBounds) {
- synchronized (mWindowMap) {
- getNonDecorInsetsLocked(mTmpRect2);
- final DisplayInfo di = getDefaultDisplayInfoLocked();
- mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
- subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
- }
- }
-
- void subtractInsets(Rect display, Rect insets, Rect inOutBounds) {
+ void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
mTmpRect3.set(display);
mTmpRect3.inset(insets);
inOutBounds.intersect(mTmpRect3);
}
- /**
- * Calculates the smallest width for a task given the {@param bounds}. It does that by iterating
- * across all screen orientations, and returns the minimum of the task width taking into account
- * that the bounds might change because the snap algorithm snaps to a different value.
- *
- * @return the smallest width to be used in the Configuration, in dips
- */
- public int getSmallestWidthForTaskBounds(Rect bounds) {
- synchronized (mWindowMap) {
- // TODO(multi-display): Use correct display content here
- return getDefaultDisplayContentLocked().getDockedDividerController()
- .getSmallestWidthDpForBounds(bounds);
- }
- }
-
MousePositionTracker mMousePositionTracker = new MousePositionTracker();
private static class MousePositionTracker implements PointerEventListener {