Merge "Unify Aspect Ratio Logic in ActivityRecord" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0e7ef13b6a
@@ -677,8 +677,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
private boolean mInSizeCompatModeForBounds = false;
|
private boolean mInSizeCompatModeForBounds = false;
|
||||||
|
|
||||||
// Whether the aspect ratio restrictions applied to the activity bounds in applyAspectRatio().
|
// 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;
|
private boolean mIsAspectRatioApplied = false;
|
||||||
|
|
||||||
// Bounds populated in resolveFixedOrientationConfiguration when this activity is letterboxed
|
// 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 Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
|
||||||
final int parentWidth = parentBounds.width();
|
final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
|
||||||
final int parentHeight = parentBounds.height();
|
final Rect containingBounds = new Rect();
|
||||||
float aspect = Math.max(parentWidth, parentHeight)
|
final Rect containingAppBounds = new Rect();
|
||||||
/ (float) Math.min(parentWidth, parentHeight);
|
// 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
|
// Override from config_fixedOrientationLetterboxAspectRatio or via ADB with
|
||||||
// set-fixed-orientation-letterbox-aspect-ratio.
|
// set-fixed-orientation-letterbox-aspect-ratio.
|
||||||
final float letterboxAspectRatioOverride =
|
final float letterboxAspectRatioOverride =
|
||||||
mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
|
mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
|
||||||
aspect = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
|
final float desiredAspectRatio =
|
||||||
? letterboxAspectRatioOverride : aspect;
|
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
|
// Vertically center if orientation is landscape. Bounds will later be horizontally centered
|
||||||
// order to use the extra available space.
|
// in {@link updateResolvedBoundsHorizontalPosition()} regardless of orientation.
|
||||||
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);
|
|
||||||
if (forcedOrientation == ORIENTATION_LANDSCAPE) {
|
if (forcedOrientation == ORIENTATION_LANDSCAPE) {
|
||||||
final int height = (int) Math.rint(parentWidth / aspect);
|
final int offsetY = parentBounds.centerY() - resolvedBounds.centerY();
|
||||||
final int top = parentBounds.centerY() - height / 2;
|
resolvedBounds.offset(0, offsetY);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCompatDisplayInsets != null) {
|
if (mCompatDisplayInsets != null) {
|
||||||
@@ -7342,8 +7347,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
// then they should be aligned later in #updateResolvedBoundsHorizontalPosition().
|
// then they should be aligned later in #updateResolvedBoundsHorizontalPosition().
|
||||||
if (!mTmpBounds.isEmpty()) {
|
if (!mTmpBounds.isEmpty()) {
|
||||||
resolvedBounds.set(mTmpBounds);
|
resolvedBounds.set(mTmpBounds);
|
||||||
// Exclude the horizontal decor area.
|
|
||||||
resolvedBounds.left = parentAppBounds.left;
|
|
||||||
}
|
}
|
||||||
if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) {
|
if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) {
|
||||||
// Compute the configuration based on the resolved bounds. If aspect ratio doesn't
|
// 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 =
|
mIsAspectRatioApplied =
|
||||||
applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
|
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
|
// 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
|
// 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
|
// Align to top of parent (bounds) - this is a UX choice and exclude the horizontal decor
|
||||||
// if needed. Horizontal position is adjusted in updateResolvedBoundsHorizontalPosition.
|
// if needed. Horizontal position is adjusted in updateResolvedBoundsHorizontalPosition.
|
||||||
// Above coordinates are in "@" space, now place "*" and "#" to screen space.
|
// 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 screenPosX = fillContainer ? containerBounds.left : containerAppBounds.left;
|
||||||
final int screenPosY = containerBounds.top;
|
final int screenPosY = containerBounds.top;
|
||||||
if (screenPosX != 0 || screenPosY != 0) {
|
if (screenPosX != 0 || screenPosY != 0) {
|
||||||
@@ -7713,6 +7710,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
return true;
|
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
|
* Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
|
||||||
* made to outBounds.
|
* 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.
|
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
|
||||||
private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
|
private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
|
||||||
Rect containingBounds) {
|
Rect containingBounds, float desiredAspectRatio, boolean fixedOrientationLetterboxed) {
|
||||||
final float maxAspectRatio = info.getMaxAspectRatio();
|
final float maxAspectRatio = info.getMaxAspectRatio();
|
||||||
final Task rootTask = getRootTask();
|
final Task rootTask = getRootTask();
|
||||||
final float minAspectRatio = info.getMinAspectRatio();
|
final float minAspectRatio = info.getMinAspectRatio();
|
||||||
|
|
||||||
if (task == null || rootTask == null
|
if (task == null || rootTask == null
|
||||||
|| (inMultiWindowMode() && !shouldCreateCompatDisplayInsets())
|
|| (inMultiWindowMode() && !shouldCreateCompatDisplayInsets()
|
||||||
|| (maxAspectRatio == 0 && minAspectRatio == 0)
|
&& !fixedOrientationLetterboxed)
|
||||||
|
|| (maxAspectRatio < 1 && minAspectRatio < 1 && desiredAspectRatio < 1)
|
||||||
|| isInVrUiMode(getConfiguration())) {
|
|| isInVrUiMode(getConfiguration())) {
|
||||||
// We don't enforce aspect ratio if the activity task is in multiwindow unless it
|
// We don't enforce aspect ratio if the activity task is in multiwindow unless it is in
|
||||||
// is in size-compat mode. We also don't set it if we are in VR mode.
|
// size-compat mode or is letterboxed from fixed orientation. We also don't set it if we
|
||||||
|
// are in VR mode.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7739,20 +7744,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
final int containingAppHeight = containingAppBounds.height();
|
final int containingAppHeight = containingAppBounds.height();
|
||||||
final float containingRatio = computeAspectRatio(containingAppBounds);
|
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 activityWidth = containingAppWidth;
|
||||||
int activityHeight = containingAppHeight;
|
int activityHeight = containingAppHeight;
|
||||||
|
|
||||||
if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
|
if (containingRatio > desiredAspectRatio) {
|
||||||
if (containingAppWidth < containingAppHeight) {
|
if (containingAppWidth < containingAppHeight) {
|
||||||
// Width is the shorter side, so we use that to figure-out what the max. height
|
// Width is the shorter side, so we use that to figure-out what the max. height
|
||||||
// should be given the aspect ratio.
|
// should be given the aspect ratio.
|
||||||
activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
|
activityHeight = (int) ((activityWidth * desiredAspectRatio) + 0.5f);
|
||||||
} else {
|
} else {
|
||||||
// Height is the shorter side, so we use that to figure-out what the max. width
|
// Height is the shorter side, so we use that to figure-out what the max. width
|
||||||
// should be given the aspect ratio.
|
// 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;
|
boolean adjustWidth;
|
||||||
switch (getRequestedConfigurationOrientation()) {
|
switch (getRequestedConfigurationOrientation()) {
|
||||||
case ORIENTATION_LANDSCAPE:
|
case ORIENTATION_LANDSCAPE:
|
||||||
@@ -7780,9 +7795,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (adjustWidth) {
|
if (adjustWidth) {
|
||||||
activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
|
activityWidth = (int) ((activityHeight / desiredAspectRatio) + 0.5f);
|
||||||
} else {
|
} 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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -401,6 +401,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
assertFitted();
|
assertFitted();
|
||||||
|
|
||||||
final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();
|
final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();
|
||||||
|
final Rect currentAppBounds = mActivity.getWindowConfiguration().getAppBounds();
|
||||||
final Rect originalBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
|
final Rect originalBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
|
||||||
|
|
||||||
final int notchHeight = 100;
|
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
|
// 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.
|
// display with keeping portrait bounds [200, 0 - 700, 1000] in center.
|
||||||
assertEquals(newDisplayBounds.height(), currentBounds.height());
|
assertEquals(newDisplayBounds.height(), currentBounds.height());
|
||||||
assertEquals(currentBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(),
|
assertEquals(currentAppBounds.height() * newDisplayBounds.height()
|
||||||
currentBounds.width());
|
/ newDisplayBounds.width(), currentAppBounds.width());
|
||||||
assertFitted();
|
assertFitted();
|
||||||
// The appBounds should be [200, 100 - 700, 1000].
|
// The appBounds should be [200, 100 - 700, 1000].
|
||||||
final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds();
|
final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds();
|
||||||
|
|||||||
Reference in New Issue
Block a user