Unify Aspect Ratio Logic in ActivityRecord
Use the existing aspect ratio logic when resolving
fixed orientation bounds.
Test: atest AppConfigurationTests AspectRatioTests SizeCompatTests
ActivityRecordTests TaskTests CompatChangeTests
Bug: b/184772344 b/182268157
Change-Id: I174661f69dc90d57c0c966baa2360adb6a5ab8a4
Merged-In: I40a071399e3bc159a20ade917da4c94cace0524e
This commit is contained in:
@@ -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
|
||||
@@ -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;
|
||||
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);
|
||||
|
||||
// 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);
|
||||
// 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) {
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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) {
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user