Loading services/core/java/com/android/server/wm/ActivityRecord.java +73 −51 Original line number Diff line number Diff line Loading @@ -677,8 +677,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private boolean mInSizeCompatModeForBounds = false; // Whether the aspect ratio restrictions applied to the activity bounds in applyAspectRatio(). // TODO(b/182268157): Aspect ratio can also be applie in resolveFixedOrientationConfiguration // but that isn't reflected in this boolean. private boolean mIsAspectRatioApplied = false; // Bounds populated in resolveFixedOrientationConfiguration when this activity is letterboxed Loading Loading @@ -7266,41 +7264,48 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } final Rect parentBounds = newParentConfig.windowConfiguration.getBounds(); final int parentWidth = parentBounds.width(); final int parentHeight = parentBounds.height(); float aspect = Math.max(parentWidth, parentHeight) / (float) Math.min(parentWidth, parentHeight); final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds(); final Rect containingBounds = new Rect(); final Rect containingAppBounds = new Rect(); // Need to shrink the containing bounds into a square because the parent orientation does // not match the activity requested orientation. if (forcedOrientation == ORIENTATION_LANDSCAPE) { // Shrink height to match width. Position height within app bounds. final int bottom = Math.min(parentAppBounds.top + parentBounds.width(), parentAppBounds.bottom); containingBounds.set(parentBounds.left, parentAppBounds.top, parentBounds.right, bottom); containingAppBounds.set(parentAppBounds.left, parentAppBounds.top, parentAppBounds.right, bottom); } else { // Shrink width to match height. Position width within app bounds. final int right = Math.min(parentAppBounds.left + parentBounds.height(), parentAppBounds.right); containingBounds.set(parentAppBounds.left, parentBounds.top, right, parentBounds.bottom); containingAppBounds.set(parentAppBounds.left, parentAppBounds.top, right, parentAppBounds.bottom); } Rect mTmpFullBounds = new Rect(resolvedBounds); resolvedBounds.set(containingBounds); // Override from config_fixedOrientationLetterboxAspectRatio or via ADB with // set-fixed-orientation-letterbox-aspect-ratio. final float letterboxAspectRatioOverride = mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(); aspect = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : aspect; // Adjust the fixed orientation letterbox bounds to fit the app request aspect ratio in // order to use the extra available space. final float maxAspectRatio = info.getMaxAspectRatio(); final float minAspectRatio = info.getMinAspectRatio(); if (aspect > maxAspectRatio && maxAspectRatio != 0) { aspect = maxAspectRatio; } else if (aspect < minAspectRatio) { aspect = minAspectRatio; } // Store the current bounds to be able to revert to size compat mode values below if needed. Rect mTmpFullBounds = new Rect(resolvedBounds); final float desiredAspectRatio = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : computeAspectRatio(parentBounds); // Apply aspect ratio to resolved bounds mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds, desiredAspectRatio, true); // Vertically center if orientation is landscape. Bounds will later be horizontally centered // in {@link updateResolvedBoundsHorizontalPosition()} regardless of orientation. if (forcedOrientation == ORIENTATION_LANDSCAPE) { final int height = (int) Math.rint(parentWidth / aspect); final int top = parentBounds.centerY() - height / 2; resolvedBounds.set(parentBounds.left, top, parentBounds.right, top + height); } else { final int width = (int) Math.rint(parentHeight / aspect); final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds(); final int left = width <= parentAppBounds.width() // Avoid overlapping with the horizontal decor area when possible. ? parentAppBounds.left : parentBounds.centerX() - width / 2; resolvedBounds.set(left, parentBounds.top, left + width, parentBounds.bottom); final int offsetY = parentBounds.centerY() - resolvedBounds.centerY(); resolvedBounds.offset(0, offsetY); } if (mCompatDisplayInsets != null) { Loading Loading @@ -7342,8 +7347,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // then they should be aligned later in #updateResolvedBoundsHorizontalPosition(). if (!mTmpBounds.isEmpty()) { resolvedBounds.set(mTmpBounds); // Exclude the horizontal decor area. resolvedBounds.left = parentAppBounds.left; } if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) { // Compute the configuration based on the resolved bounds. If aspect ratio doesn't Loading Loading @@ -7404,13 +7407,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds); } // If the bounds are restricted by fixed aspect ratio, the resolved bounds should be put in // the container app bounds. Otherwise the entire container bounds are available. final boolean fillContainer = resolvedBounds.equals(containingBounds); if (!fillContainer) { // The horizontal position should not cover insets. resolvedBounds.left = containingAppBounds.left; } // Use resolvedBounds to compute other override configurations such as appBounds. The bounds // are calculated in compat container space. The actual position on screen will be applied Loading Loading @@ -7477,6 +7473,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Align to top of parent (bounds) - this is a UX choice and exclude the horizontal decor // if needed. Horizontal position is adjusted in updateResolvedBoundsHorizontalPosition. // Above coordinates are in "@" space, now place "*" and "#" to screen space. final boolean fillContainer = resolvedBounds.equals(containingBounds); final int screenPosX = fillContainer ? containerBounds.left : containerAppBounds.left; final int screenPosY = containerBounds.top; if (screenPosX != 0 || screenPosY != 0) { Loading Loading @@ -7713,6 +7710,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return true; } private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds, Rect containingBounds) { return applyAspectRatio(outBounds, containingAppBounds, containingBounds, 0 /* desiredAspectRatio */, false /* fixedOrientationLetterboxed */); } /** * Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is * made to outBounds. Loading @@ -7721,17 +7724,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer. private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds, Rect containingBounds) { Rect containingBounds, float desiredAspectRatio, boolean fixedOrientationLetterboxed) { final float maxAspectRatio = info.getMaxAspectRatio(); final Task rootTask = getRootTask(); final float minAspectRatio = info.getMinAspectRatio(); if (task == null || rootTask == null || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets()) || (maxAspectRatio == 0 && minAspectRatio == 0) || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets() && !fixedOrientationLetterboxed) || (maxAspectRatio < 1 && minAspectRatio < 1 && desiredAspectRatio < 1) || isInVrUiMode(getConfiguration())) { // We don't enforce aspect ratio if the activity task is in multiwindow unless it // is in size-compat mode. We also don't set it if we are in VR mode. // We don't enforce aspect ratio if the activity task is in multiwindow unless it is in // size-compat mode or is letterboxed from fixed orientation. We also don't set it if we // are in VR mode. return false; } Loading @@ -7739,20 +7744,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final int containingAppHeight = containingAppBounds.height(); final float containingRatio = computeAspectRatio(containingAppBounds); if (desiredAspectRatio < 1) { desiredAspectRatio = containingRatio; } if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) { desiredAspectRatio = maxAspectRatio; } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) { desiredAspectRatio = minAspectRatio; } int activityWidth = containingAppWidth; int activityHeight = containingAppHeight; if (containingRatio > maxAspectRatio && maxAspectRatio != 0) { if (containingRatio > desiredAspectRatio) { if (containingAppWidth < containingAppHeight) { // Width is the shorter side, so we use that to figure-out what the max. height // should be given the aspect ratio. activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f); activityHeight = (int) ((activityWidth * desiredAspectRatio) + 0.5f); } else { // Height is the shorter side, so we use that to figure-out what the max. width // should be given the aspect ratio. activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f); activityWidth = (int) ((activityHeight * desiredAspectRatio) + 0.5f); } } else if (containingRatio < minAspectRatio) { } else if (containingRatio < desiredAspectRatio) { boolean adjustWidth; switch (getRequestedConfigurationOrientation()) { case ORIENTATION_LANDSCAPE: Loading Loading @@ -7780,9 +7795,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A break; } if (adjustWidth) { activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f); activityWidth = (int) ((activityHeight / desiredAspectRatio) + 0.5f); } else { activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f); activityHeight = (int) ((activityWidth / desiredAspectRatio) + 0.5f); } } Loading @@ -7806,6 +7821,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } outBounds.set(containingBounds.left, containingBounds.top, right, bottom); // If the bounds are restricted by fixed aspect ratio, then out bounds should be put in the // container app bounds. Otherwise the entire container bounds are available. if (!outBounds.equals(containingBounds)) { // The horizontal position should not cover insets. outBounds.left = containingAppBounds.left; } return true; } Loading services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +3 −2 Original line number Diff line number Diff line Loading @@ -401,6 +401,7 @@ public class SizeCompatTests extends WindowTestsBase { assertFitted(); final Rect currentBounds = mActivity.getWindowConfiguration().getBounds(); final Rect currentAppBounds = mActivity.getWindowConfiguration().getAppBounds(); final Rect originalBounds = new Rect(mActivity.getWindowConfiguration().getBounds()); final int notchHeight = 100; Loading Loading @@ -428,8 +429,8 @@ public class SizeCompatTests extends WindowTestsBase { // Because the display cannot rotate, the portrait activity will fit the short side of // display with keeping portrait bounds [200, 0 - 700, 1000] in center. assertEquals(newDisplayBounds.height(), currentBounds.height()); assertEquals(currentBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(), currentBounds.width()); assertEquals(currentAppBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(), currentAppBounds.width()); assertFitted(); // The appBounds should be [200, 100 - 700, 1000]. final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds(); Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +73 −51 Original line number Diff line number Diff line Loading @@ -677,8 +677,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private boolean mInSizeCompatModeForBounds = false; // Whether the aspect ratio restrictions applied to the activity bounds in applyAspectRatio(). // TODO(b/182268157): Aspect ratio can also be applie in resolveFixedOrientationConfiguration // but that isn't reflected in this boolean. private boolean mIsAspectRatioApplied = false; // Bounds populated in resolveFixedOrientationConfiguration when this activity is letterboxed Loading Loading @@ -7266,41 +7264,48 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } final Rect parentBounds = newParentConfig.windowConfiguration.getBounds(); final int parentWidth = parentBounds.width(); final int parentHeight = parentBounds.height(); float aspect = Math.max(parentWidth, parentHeight) / (float) Math.min(parentWidth, parentHeight); final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds(); final Rect containingBounds = new Rect(); final Rect containingAppBounds = new Rect(); // Need to shrink the containing bounds into a square because the parent orientation does // not match the activity requested orientation. if (forcedOrientation == ORIENTATION_LANDSCAPE) { // Shrink height to match width. Position height within app bounds. final int bottom = Math.min(parentAppBounds.top + parentBounds.width(), parentAppBounds.bottom); containingBounds.set(parentBounds.left, parentAppBounds.top, parentBounds.right, bottom); containingAppBounds.set(parentAppBounds.left, parentAppBounds.top, parentAppBounds.right, bottom); } else { // Shrink width to match height. Position width within app bounds. final int right = Math.min(parentAppBounds.left + parentBounds.height(), parentAppBounds.right); containingBounds.set(parentAppBounds.left, parentBounds.top, right, parentBounds.bottom); containingAppBounds.set(parentAppBounds.left, parentAppBounds.top, right, parentAppBounds.bottom); } Rect mTmpFullBounds = new Rect(resolvedBounds); resolvedBounds.set(containingBounds); // Override from config_fixedOrientationLetterboxAspectRatio or via ADB with // set-fixed-orientation-letterbox-aspect-ratio. final float letterboxAspectRatioOverride = mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(); aspect = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : aspect; // Adjust the fixed orientation letterbox bounds to fit the app request aspect ratio in // order to use the extra available space. final float maxAspectRatio = info.getMaxAspectRatio(); final float minAspectRatio = info.getMinAspectRatio(); if (aspect > maxAspectRatio && maxAspectRatio != 0) { aspect = maxAspectRatio; } else if (aspect < minAspectRatio) { aspect = minAspectRatio; } // Store the current bounds to be able to revert to size compat mode values below if needed. Rect mTmpFullBounds = new Rect(resolvedBounds); final float desiredAspectRatio = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : computeAspectRatio(parentBounds); // Apply aspect ratio to resolved bounds mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds, desiredAspectRatio, true); // Vertically center if orientation is landscape. Bounds will later be horizontally centered // in {@link updateResolvedBoundsHorizontalPosition()} regardless of orientation. if (forcedOrientation == ORIENTATION_LANDSCAPE) { final int height = (int) Math.rint(parentWidth / aspect); final int top = parentBounds.centerY() - height / 2; resolvedBounds.set(parentBounds.left, top, parentBounds.right, top + height); } else { final int width = (int) Math.rint(parentHeight / aspect); final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds(); final int left = width <= parentAppBounds.width() // Avoid overlapping with the horizontal decor area when possible. ? parentAppBounds.left : parentBounds.centerX() - width / 2; resolvedBounds.set(left, parentBounds.top, left + width, parentBounds.bottom); final int offsetY = parentBounds.centerY() - resolvedBounds.centerY(); resolvedBounds.offset(0, offsetY); } if (mCompatDisplayInsets != null) { Loading Loading @@ -7342,8 +7347,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // then they should be aligned later in #updateResolvedBoundsHorizontalPosition(). if (!mTmpBounds.isEmpty()) { resolvedBounds.set(mTmpBounds); // Exclude the horizontal decor area. resolvedBounds.left = parentAppBounds.left; } if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) { // Compute the configuration based on the resolved bounds. If aspect ratio doesn't Loading Loading @@ -7404,13 +7407,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds); } // If the bounds are restricted by fixed aspect ratio, the resolved bounds should be put in // the container app bounds. Otherwise the entire container bounds are available. final boolean fillContainer = resolvedBounds.equals(containingBounds); if (!fillContainer) { // The horizontal position should not cover insets. resolvedBounds.left = containingAppBounds.left; } // Use resolvedBounds to compute other override configurations such as appBounds. The bounds // are calculated in compat container space. The actual position on screen will be applied Loading Loading @@ -7477,6 +7473,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Align to top of parent (bounds) - this is a UX choice and exclude the horizontal decor // if needed. Horizontal position is adjusted in updateResolvedBoundsHorizontalPosition. // Above coordinates are in "@" space, now place "*" and "#" to screen space. final boolean fillContainer = resolvedBounds.equals(containingBounds); final int screenPosX = fillContainer ? containerBounds.left : containerAppBounds.left; final int screenPosY = containerBounds.top; if (screenPosX != 0 || screenPosY != 0) { Loading Loading @@ -7713,6 +7710,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return true; } private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds, Rect containingBounds) { return applyAspectRatio(outBounds, containingAppBounds, containingBounds, 0 /* desiredAspectRatio */, false /* fixedOrientationLetterboxed */); } /** * Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is * made to outBounds. Loading @@ -7721,17 +7724,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer. private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds, Rect containingBounds) { Rect containingBounds, float desiredAspectRatio, boolean fixedOrientationLetterboxed) { final float maxAspectRatio = info.getMaxAspectRatio(); final Task rootTask = getRootTask(); final float minAspectRatio = info.getMinAspectRatio(); if (task == null || rootTask == null || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets()) || (maxAspectRatio == 0 && minAspectRatio == 0) || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets() && !fixedOrientationLetterboxed) || (maxAspectRatio < 1 && minAspectRatio < 1 && desiredAspectRatio < 1) || isInVrUiMode(getConfiguration())) { // We don't enforce aspect ratio if the activity task is in multiwindow unless it // is in size-compat mode. We also don't set it if we are in VR mode. // We don't enforce aspect ratio if the activity task is in multiwindow unless it is in // size-compat mode or is letterboxed from fixed orientation. We also don't set it if we // are in VR mode. return false; } Loading @@ -7739,20 +7744,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final int containingAppHeight = containingAppBounds.height(); final float containingRatio = computeAspectRatio(containingAppBounds); if (desiredAspectRatio < 1) { desiredAspectRatio = containingRatio; } if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) { desiredAspectRatio = maxAspectRatio; } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) { desiredAspectRatio = minAspectRatio; } int activityWidth = containingAppWidth; int activityHeight = containingAppHeight; if (containingRatio > maxAspectRatio && maxAspectRatio != 0) { if (containingRatio > desiredAspectRatio) { if (containingAppWidth < containingAppHeight) { // Width is the shorter side, so we use that to figure-out what the max. height // should be given the aspect ratio. activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f); activityHeight = (int) ((activityWidth * desiredAspectRatio) + 0.5f); } else { // Height is the shorter side, so we use that to figure-out what the max. width // should be given the aspect ratio. activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f); activityWidth = (int) ((activityHeight * desiredAspectRatio) + 0.5f); } } else if (containingRatio < minAspectRatio) { } else if (containingRatio < desiredAspectRatio) { boolean adjustWidth; switch (getRequestedConfigurationOrientation()) { case ORIENTATION_LANDSCAPE: Loading Loading @@ -7780,9 +7795,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A break; } if (adjustWidth) { activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f); activityWidth = (int) ((activityHeight / desiredAspectRatio) + 0.5f); } else { activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f); activityHeight = (int) ((activityWidth / desiredAspectRatio) + 0.5f); } } Loading @@ -7806,6 +7821,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } outBounds.set(containingBounds.left, containingBounds.top, right, bottom); // If the bounds are restricted by fixed aspect ratio, then out bounds should be put in the // container app bounds. Otherwise the entire container bounds are available. if (!outBounds.equals(containingBounds)) { // The horizontal position should not cover insets. outBounds.left = containingAppBounds.left; } return true; } Loading
services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +3 −2 Original line number Diff line number Diff line Loading @@ -401,6 +401,7 @@ public class SizeCompatTests extends WindowTestsBase { assertFitted(); final Rect currentBounds = mActivity.getWindowConfiguration().getBounds(); final Rect currentAppBounds = mActivity.getWindowConfiguration().getAppBounds(); final Rect originalBounds = new Rect(mActivity.getWindowConfiguration().getBounds()); final int notchHeight = 100; Loading Loading @@ -428,8 +429,8 @@ public class SizeCompatTests extends WindowTestsBase { // Because the display cannot rotate, the portrait activity will fit the short side of // display with keeping portrait bounds [200, 0 - 700, 1000] in center. assertEquals(newDisplayBounds.height(), currentBounds.height()); assertEquals(currentBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(), currentBounds.width()); assertEquals(currentAppBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(), currentAppBounds.width()); assertFitted(); // The appBounds should be [200, 100 - 700, 1000]. final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds(); Loading