diff options
| author | 2017-02-16 16:39:57 +0000 | |
|---|---|---|
| committer | 2017-02-16 16:40:01 +0000 | |
| commit | ba422045d793564a9e69f5fbd0fa28255edfeb1c (patch) | |
| tree | 8c39ef2004bc2beba4d0f1387290728b76e9448e | |
| parent | 04c959a3d0b2a3c4a44167d4a7429934d8a220cf (diff) | |
| parent | bdc646f5d514259d9aae975bac64363947db0d32 (diff) | |
Merge "Reducing number of configuration changes during PiP transition."
6 files changed, 149 insertions, 122 deletions
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 1b193825c41d..082b6b50fd49 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; 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_FORCE_RESIZEABLE; 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.CompatibilityInfo; 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 @@ final class ActivityRecord implements AppWindowContainerListener { /** * 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 @@ final class ActivityRecord implements AppWindowContainerListener { 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 @@ final class ActivityRecord implements AppWindowContainerListener { // 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 520d4ee87592..f8645d65fd92 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.IPackageManager; 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.app.IVoiceInteractor; 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 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta 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 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta 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 class TaskRecord extends ConfigurationContainer implements TaskWindowConta 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 0a92a8198a52..75a79fd0b55f 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 @@ public class DockedStackDividerController implements DimLayerUser { 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 @@ public class DockedStackDividerController implements DimLayerUser { 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 36d07e01e5c1..142f69a3e583 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.Looper; 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 @@ public class StackWindowController 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 @@ public class StackWindowController } } + /** + * 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 b09d69996974..b9429f48d586 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 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye @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 122db7e784cc..ad8fb8c5f73b 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 @@ public class WindowManagerService extends IWindowManager.Stub } } - 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 { |