Merge "Unify Aspect Ratio Logic in ActivityRecord" into sc-dev

This commit is contained in:
Shivam Agrawal
2021-06-22 21:07:03 +00:00
committed by Android (Google) Code Review
2 changed files with 75 additions and 52 deletions

View File

@@ -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;
}

View File

@@ -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();