Merge "Letterbox positioning (1/4): Consolidate activity and task letterboxing" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
00f8bce038
@@ -40,8 +40,11 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||
import static android.app.WindowConfiguration.activityTypeToString;
|
||||
import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
|
||||
import static android.app.servertransaction.TransferSplashScreenViewStateItem.ATTACH_TO;
|
||||
import static android.app.servertransaction.TransferSplashScreenViewStateItem.HANDOVER_TO;
|
||||
import static android.content.Intent.ACTION_MAIN;
|
||||
@@ -209,6 +212,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
|
||||
import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
|
||||
import static com.android.server.wm.WindowManagerService.LETTERBOX_BACKGROUND_SOLID_COLOR;
|
||||
import static com.android.server.wm.WindowManagerService.MIN_TASK_LETTERBOX_ASPECT_RATIO;
|
||||
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
|
||||
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
|
||||
import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
|
||||
@@ -557,7 +561,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
|
||||
/**
|
||||
* The precomputed display insets for resolving configuration. It will be non-null if
|
||||
* {@link #shouldUseSizeCompatMode} returns {@code true}.
|
||||
* {@link #shouldCreateCompatDisplayInsets} returns {@code true}.
|
||||
*/
|
||||
private CompatDisplayInsets mCompatDisplayInsets;
|
||||
|
||||
@@ -648,6 +652,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
*/
|
||||
private Rect mSizeCompatBounds;
|
||||
|
||||
// Whether this activity is in size compatibility mode because its bounds don't fit in parent
|
||||
// naturally.
|
||||
private boolean mInSizeCompatModeForBounds = false;
|
||||
|
||||
// Whether this activity is letterboxed for fixed orientation. If letterboxed due to fixed
|
||||
// orientation then aspect ratio restrictions are also already respected.
|
||||
// This happens when an activity has fixed orientation which doesn't match orientation of the
|
||||
// parent because a display is ignoring orientation request or fixed to user rotation.
|
||||
// See WindowManagerService#getIgnoreOrientationRequest and
|
||||
// WindowManagerService#getFixedToUserRotation for more context.
|
||||
private boolean mIsLetterboxedForFixedOrientationAndAspectRatio = false;
|
||||
|
||||
// activity is not displayed?
|
||||
// TODO: rename to mNoDisplay
|
||||
@VisibleForTesting
|
||||
@@ -1296,9 +1312,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// TODO(b/36505427): Maybe this call should be moved inside
|
||||
// updateOverrideConfiguration()
|
||||
newTask.updateOverrideConfigurationFromLaunchBounds();
|
||||
// Make sure override configuration is up-to-date before using to create window
|
||||
// controller.
|
||||
updateSizeCompatMode();
|
||||
// When an activity is started directly into a split-screen fullscreen root task, we
|
||||
// need to update the initial multi-window modes so that the callbacks are scheduled
|
||||
// correctly when the user leaves that mode.
|
||||
@@ -6718,12 +6731,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
if (onDescendantOrientationChanged(this)) {
|
||||
// The app is just becoming visible, and the parent Task has updated with the
|
||||
// orientation request. Update the size compat mode.
|
||||
updateSizeCompatMode();
|
||||
// WM Shell can override WM Core positioning (e.g. for letterboxing) so ensure
|
||||
// that WM Shell is called when an activity becomes visible. Without this, WM Core
|
||||
// will handle positioning instead of WM Shell when an app is reopened.
|
||||
// WM Shell can show additional UI elements, e.g. a restart button for size compat mode
|
||||
// so ensure that WM Shell is called when an activity becomes visible.
|
||||
task.dispatchTaskInfoChangedIfNeeded(/* force= */ true);
|
||||
}
|
||||
}
|
||||
@@ -6788,7 +6797,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
* density than its parent or its bounds don't fit in parent naturally.
|
||||
*/
|
||||
boolean inSizeCompatMode() {
|
||||
if (mCompatDisplayInsets == null || !shouldUseSizeCompatMode()
|
||||
if (mInSizeCompatModeForBounds) {
|
||||
return true;
|
||||
}
|
||||
if (mCompatDisplayInsets == null || !shouldCreateCompatDisplayInsets()
|
||||
// The orientation is different from parent when transforming.
|
||||
|| isFixedRotationTransforming()) {
|
||||
return false;
|
||||
@@ -6798,70 +6810,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// The app bounds hasn't been computed yet.
|
||||
return false;
|
||||
}
|
||||
|
||||
final Configuration parentConfig = getParent().getConfiguration();
|
||||
// Although colorMode, screenLayout, smallestScreenWidthDp are also fixed, generally these
|
||||
// fields should be changed with density and bounds, so here only compares the most
|
||||
// significant field.
|
||||
if (parentConfig.densityDpi != getConfiguration().densityDpi) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
|
||||
final int appWidth = appBounds.width();
|
||||
final int appHeight = appBounds.height();
|
||||
final int parentAppWidth = parentAppBounds.width();
|
||||
final int parentAppHeight = parentAppBounds.height();
|
||||
if (parentAppWidth == appWidth && parentAppHeight == appHeight) {
|
||||
// Matched the parent bounds.
|
||||
return false;
|
||||
}
|
||||
if (parentAppWidth > appWidth && parentAppHeight > appHeight) {
|
||||
// Both sides are smaller than the parent.
|
||||
return true;
|
||||
}
|
||||
if (parentAppWidth < appWidth || parentAppHeight < appHeight) {
|
||||
// One side is larger than the parent.
|
||||
return true;
|
||||
}
|
||||
|
||||
// The rest of the condition is that only one side is smaller than the parent, but it still
|
||||
// needs to exclude the cases where the size is limited by the fixed aspect ratio.
|
||||
if (info.maxAspectRatio > 0) {
|
||||
final float aspectRatio = (0.5f + Math.max(appWidth, appHeight))
|
||||
/ Math.min(appWidth, appHeight);
|
||||
if (aspectRatio >= info.maxAspectRatio) {
|
||||
// The current size has reached the max aspect ratio.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (info.minAspectRatio > 0) {
|
||||
// The activity should have at least the min aspect ratio, so this checks if the parent
|
||||
// still has available space to provide larger aspect ratio.
|
||||
final float parentAspectRatio = (0.5f + Math.max(parentAppWidth, parentAppHeight))
|
||||
/ Math.min(parentAppWidth, parentAppHeight);
|
||||
if (parentAspectRatio <= info.minAspectRatio) {
|
||||
// The long side has reached the parent.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return parentConfig.densityDpi != getConfiguration().densityDpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the activity will keep the bounds and screen configuration when it was first
|
||||
* launched, no matter how its parent changes.
|
||||
*
|
||||
* <p>If {@true}, then {@link CompatDisplayInsets} will be created in {@link
|
||||
* #resolveOverrideConfiguration} to "freeze" activity bounds and insets.
|
||||
*
|
||||
* @return {@code true} if this activity is declared as non-resizable and fixed orientation or
|
||||
* aspect ratio.
|
||||
*/
|
||||
boolean shouldUseSizeCompatMode() {
|
||||
boolean shouldCreateCompatDisplayInsets() {
|
||||
if (info.supportsSizeChanges() != ActivityInfo.SIZE_CHANGES_UNSUPPORTED) {
|
||||
return false;
|
||||
}
|
||||
if (inMultiWindowMode() || getWindowConfiguration().hasWindowDecorCaption()) {
|
||||
final ActivityRecord root = task != null ? task.getRootActivity() : null;
|
||||
if (root != null && root != this && !root.shouldUseSizeCompatMode()) {
|
||||
if (root != null && root != this && !root.shouldCreateCompatDisplayInsets()) {
|
||||
// If the root activity doesn't use size compatibility mode, the activities above
|
||||
// are forced to be the same for consistent visual appearance.
|
||||
return false;
|
||||
@@ -6883,25 +6855,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
|
||||
private void updateSizeCompatMode() {
|
||||
if (mCompatDisplayInsets != null || !shouldUseSizeCompatMode()) {
|
||||
private void updateCompatDisplayInsets(@Nullable Rect fixedOrientationBounds) {
|
||||
if (mCompatDisplayInsets != null || !shouldCreateCompatDisplayInsets()) {
|
||||
// The override configuration is set only once in size compatibility mode.
|
||||
return;
|
||||
}
|
||||
final Configuration parentConfig = getParent().getConfiguration();
|
||||
if (!hasProcess() && !isConfigurationCompatible(parentConfig)) {
|
||||
// Don't compute when launching in fullscreen and the fixed orientation is not the
|
||||
// current orientation. It is more accurately to compute the override bounds from
|
||||
// the updated configuration after the fixed orientation is applied.
|
||||
return;
|
||||
}
|
||||
|
||||
if (task == null || (!handlesOrientationChangeFromDescendant()
|
||||
&& task.getLastTaskBoundsComputeActivity() != this)) {
|
||||
// Don't compute when Task hasn't computed its bounds for this app, because the Task can
|
||||
// be letterboxed, and its bounds may not be accurate until then.
|
||||
return;
|
||||
}
|
||||
|
||||
Configuration overrideConfig = getRequestedOverrideConfiguration();
|
||||
final Configuration fullConfig = getConfiguration();
|
||||
@@ -6924,17 +6882,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
// The role of CompatDisplayInsets is like the override bounds.
|
||||
mCompatDisplayInsets = new CompatDisplayInsets(mDisplayContent, this);
|
||||
mCompatDisplayInsets =
|
||||
new CompatDisplayInsets(mDisplayContent, this, fixedOrientationBounds);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void clearSizeCompatMode() {
|
||||
mInSizeCompatModeForBounds = false;
|
||||
mSizeCompatScale = 1f;
|
||||
mSizeCompatBounds = null;
|
||||
mCompatDisplayInsets = null;
|
||||
|
||||
// Recompute from Task because letterbox can also happen on Task level.
|
||||
task.onRequestedOverrideConfigurationChanged(task.getRequestedOverrideConfiguration());
|
||||
onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -6969,23 +6928,41 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
mTmpConfig.updateFrom(resolvedConfig);
|
||||
newParentConfiguration = mTmpConfig;
|
||||
}
|
||||
|
||||
final int windowingMode = getWindowingMode();
|
||||
// TODO(b/181207944): Consider removing the if condition and always run
|
||||
// resolveFixedOrientationConfiguration() since this should be applied for all cases.
|
||||
if (isSplitScreenWindowingMode(windowingMode)
|
||||
|| windowingMode == WINDOWING_MODE_MULTI_WINDOW
|
||||
|| windowingMode == WINDOWING_MODE_FULLSCREEN) {
|
||||
resolveFixedOrientationConfiguration(newParentConfiguration);
|
||||
}
|
||||
final Rect fixedOrientationBounds = isLetterboxedForFixedOrientationAndAspectRatio()
|
||||
? new Rect(resolvedConfig.windowConfiguration.getBounds()) : null;
|
||||
|
||||
if (mCompatDisplayInsets != null) {
|
||||
resolveSizeCompatModeConfiguration(newParentConfiguration);
|
||||
} else {
|
||||
if (inMultiWindowMode()) {
|
||||
// We ignore activities' requested orientation in multi-window modes. Task level may
|
||||
// take them into consideration when calculating bounds.
|
||||
resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
|
||||
// If the activity has requested override bounds, the configuration needs to be
|
||||
// computed accordingly.
|
||||
if (!matchParentBounds()) {
|
||||
task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration);
|
||||
}
|
||||
} else {
|
||||
resolveFullscreenConfiguration(newParentConfiguration);
|
||||
} else if (inMultiWindowMode()) {
|
||||
// We ignore activities' requested orientation in multi-window modes. They may be
|
||||
// taken into consideration in resolveFixedOrientationConfiguration call above.
|
||||
resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
|
||||
// If the activity has requested override bounds, the configuration needs to be
|
||||
// computed accordingly.
|
||||
if (!matchParentBounds()) {
|
||||
task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration);
|
||||
}
|
||||
// If activity in fullscreen mode is letterboxed because of fixed orientation then bounds
|
||||
// are already calculated in resolveFixedOrientationConfiguration.
|
||||
} else if (!isLetterboxedForFixedOrientationAndAspectRatio()) {
|
||||
resolveFullscreenConfiguration(newParentConfiguration);
|
||||
}
|
||||
|
||||
if (mVisibleRequested) {
|
||||
updateCompatDisplayInsets(fixedOrientationBounds);
|
||||
}
|
||||
|
||||
// TODO(b/175212232): Consolidate position logic from each "resolve" method above here.
|
||||
|
||||
// Assign configuration sequence number into hierarchy because there is a different way than
|
||||
// ensureActivityConfiguration() in this class that uses configuration in WindowState during
|
||||
// layout traversals.
|
||||
@@ -6993,6 +6970,109 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
getResolvedOverrideConfiguration().seq = mConfigurationSeq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this activity is letterboxed for fixed orientation. If letterboxed due to fixed
|
||||
* orientation then aspect ratio restrictions are also already respected.
|
||||
*
|
||||
* <p>This happens when an activity has fixed orientation which doesn't match orientation of the
|
||||
* parent because a display setting 'ignoreOrientationRequest' is set to true. See {@link
|
||||
* WindowManagerService#getIgnoreOrientationRequest} for more context.
|
||||
*/
|
||||
boolean isLetterboxedForFixedOrientationAndAspectRatio() {
|
||||
return mIsLetterboxedForFixedOrientationAndAspectRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes bounds (letterbox or pillarbox) when the parent doesn't handle the orientation
|
||||
* change and the requested orientation is different from the parent.
|
||||
*
|
||||
* <p>If letterboxed due to fixed orientation then aspect ratio restrictions are also applied
|
||||
* in this methiod.
|
||||
*/
|
||||
private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig) {
|
||||
mIsLetterboxedForFixedOrientationAndAspectRatio = false;
|
||||
if (handlesOrientationChangeFromDescendant()) {
|
||||
// No need to letterbox because of fixed orientation. Display will handle
|
||||
// fixed-orientation requests.
|
||||
return;
|
||||
}
|
||||
|
||||
final Rect resolvedBounds =
|
||||
getResolvedOverrideConfiguration().windowConfiguration.getBounds();
|
||||
final int parentOrientation = newParentConfig.orientation;
|
||||
|
||||
// If the activity requires a different orientation (either by override or activityInfo),
|
||||
// make it fit the available bounds by scaling down its bounds.
|
||||
final int forcedOrientation = getRequestedConfigurationOrientation();
|
||||
if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCompatDisplayInsets != null && !mCompatDisplayInsets.mIsInFixedOrientationLetterbox) {
|
||||
// App prefers to keep its original size.
|
||||
// If the size compat is from previous fixed orientation letterboxing, we may want to
|
||||
// have fixed orientation letterbox again, otherwise it will show the size compat
|
||||
// restart button even if the restart bounds will be the same.
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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.maxAspectRatio;
|
||||
final float minAspectRatio = info.minAspectRatio;
|
||||
if (aspect > maxAspectRatio && maxAspectRatio != 0) {
|
||||
aspect = maxAspectRatio;
|
||||
} else if (aspect < minAspectRatio) {
|
||||
aspect = minAspectRatio;
|
||||
}
|
||||
|
||||
// Override from config_letterboxAspectRatio or via ADB with set-letterbox-aspect-ratio.
|
||||
// TODO(b/175212232): Rename getTaskLetterboxAspectRatio and all related methods since fixed
|
||||
// orientation letterbox is on the activity level now.
|
||||
final float letterboxAspectRatioOverride = mWmService.getTaskLetterboxAspectRatio();
|
||||
// Activity min/max aspect ratio restrictions will be respected by the activity-level
|
||||
// letterboxing (size-compat mode). Therefore this override can control the maximum screen
|
||||
// area that can be occupied by the app in the letterbox mode.
|
||||
aspect = letterboxAspectRatioOverride > MIN_TASK_LETTERBOX_ASPECT_RATIO
|
||||
? letterboxAspectRatioOverride : aspect;
|
||||
|
||||
// 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) {
|
||||
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 int left = parentBounds.centerX() - width / 2;
|
||||
resolvedBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
|
||||
}
|
||||
|
||||
if (mCompatDisplayInsets != null) {
|
||||
mCompatDisplayInsets.getBoundsByRotation(
|
||||
mTmpBounds, newParentConfig.windowConfiguration.getRotation());
|
||||
if (resolvedBounds.width() != mTmpBounds.width()
|
||||
|| resolvedBounds.height() != mTmpBounds.height()) {
|
||||
// The app shouldn't be resized, we only do fixed orientation letterboxing if the
|
||||
// compat bounds are also from the same fixed orientation letterbox. Otherwise,
|
||||
// clear the fixed orientation bounds to show app in size compat mode.
|
||||
resolvedBounds.set(mTmpFullBounds);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate app bounds using fixed orientation bounds because they will be needed later
|
||||
// for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}.
|
||||
task.computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
|
||||
mIsLetterboxedForFixedOrientationAndAspectRatio = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the configuration of activity in fullscreen mode. If the bounds are restricted by
|
||||
* aspect ratio, the position will be centered horizontally in parent's app bounds to balance
|
||||
@@ -7037,6 +7117,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
|
||||
final Configuration resolvedConfig = getResolvedOverrideConfiguration();
|
||||
final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
|
||||
|
||||
// When an activity needs to be letterboxed because of fixed orientation, use fixed
|
||||
// orientation bounds (stored in resolved bounds) instead of parent bounds since the
|
||||
// activity will be displayed within them even if it is in size compat mode. They should be
|
||||
// saved here before resolved bounds are overridden below.
|
||||
final Rect containerBounds = isLetterboxedForFixedOrientationAndAspectRatio()
|
||||
? new Rect(resolvedBounds)
|
||||
: newParentConfiguration.windowConfiguration.getBounds();
|
||||
final Rect containerAppBounds = isLetterboxedForFixedOrientationAndAspectRatio()
|
||||
? new Rect(getResolvedOverrideConfiguration().windowConfiguration.getAppBounds())
|
||||
: newParentConfiguration.windowConfiguration.getAppBounds();
|
||||
|
||||
final int requestedOrientation = getRequestedConfigurationOrientation();
|
||||
final boolean orientationRequested = requestedOrientation != ORIENTATION_UNDEFINED;
|
||||
final int orientation = orientationRequested
|
||||
@@ -7095,7 +7187,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// Below figure is an example that puts an activity which was launched in a larger container
|
||||
// into a smaller container.
|
||||
// The outermost rectangle is the real display bounds.
|
||||
// "@" is the parent app bounds.
|
||||
// "@" is the container app bounds (parent bounds or fixed orientation bouds)
|
||||
// "#" is the {@code resolvedBounds} that applies to application.
|
||||
// "*" is the {@code mSizeCompatBounds} that used to show on screen if scaled.
|
||||
// ------------------------------
|
||||
@@ -7111,19 +7203,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// The application is still layouted in "#" since it was launched, and it will be visually
|
||||
// scaled and positioned to "*".
|
||||
|
||||
final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
|
||||
|
||||
// Calculates the scale and offset to horizontal center the size compatibility bounds into
|
||||
// the region which is available to application.
|
||||
final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
|
||||
final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
|
||||
final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
|
||||
final int contentW = resolvedAppBounds.width();
|
||||
final int contentH = resolvedAppBounds.height();
|
||||
final int viewportW = parentAppBounds.width();
|
||||
final int viewportH = parentAppBounds.height();
|
||||
final int viewportW = containerAppBounds.width();
|
||||
final int viewportH = containerAppBounds.height();
|
||||
// Only allow to scale down.
|
||||
mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
|
||||
? 1f : Math.min((float) viewportW / contentW, (float) viewportH / contentH);
|
||||
final int screenTopInset = parentAppBounds.top - parentBounds.top;
|
||||
final int screenTopInset = containerAppBounds.top - containerBounds.top;
|
||||
final boolean topNotAligned = screenTopInset != resolvedAppBounds.top - resolvedBounds.top;
|
||||
if (mSizeCompatScale != 1f || topNotAligned) {
|
||||
if (mSizeCompatBounds == null) {
|
||||
@@ -7143,8 +7234,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
final int offsetX = getHorizontalCenterOffset(
|
||||
(int) viewportW, (int) (contentW * mSizeCompatScale));
|
||||
// Above coordinates are in "@" space, now place "*" and "#" to screen space.
|
||||
final int screenPosX = (fillContainer ? parentBounds.left : parentAppBounds.left) + offsetX;
|
||||
final int screenPosY = parentBounds.top;
|
||||
final int screenPosX = (fillContainer
|
||||
? containerBounds.left : containerAppBounds.left) + offsetX;
|
||||
final int screenPosY = containerBounds.top;
|
||||
if (screenPosX != 0 || screenPosY != 0) {
|
||||
if (mSizeCompatBounds != null) {
|
||||
mSizeCompatBounds.offset(screenPosX, screenPosY);
|
||||
@@ -7154,6 +7246,52 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
final int dy = screenPosY - resolvedBounds.top;
|
||||
offsetBounds(resolvedConfig, dx, dy);
|
||||
}
|
||||
|
||||
mInSizeCompatModeForBounds =
|
||||
isInSizeCompatModeForBounds(resolvedAppBounds, containerAppBounds);
|
||||
}
|
||||
|
||||
private boolean isInSizeCompatModeForBounds(final Rect appBounds, final Rect containerBounds) {
|
||||
final int appWidth = appBounds.width();
|
||||
final int appHeight = appBounds.height();
|
||||
final int containerAppWidth = containerBounds.width();
|
||||
final int containerAppHeight = containerBounds.height();
|
||||
|
||||
if (containerAppWidth == appWidth && containerAppHeight == appHeight) {
|
||||
// Matched the container bounds.
|
||||
return false;
|
||||
}
|
||||
if (containerAppWidth > appWidth && containerAppHeight > appHeight) {
|
||||
// Both sides are smaller than the container.
|
||||
return true;
|
||||
}
|
||||
if (containerAppWidth < appWidth || containerAppHeight < appHeight) {
|
||||
// One side is larger than the container.
|
||||
return true;
|
||||
}
|
||||
|
||||
// The rest of the condition is that only one side is smaller than the container, but it
|
||||
// still needs to exclude the cases where the size is limited by the fixed aspect ratio.
|
||||
if (info.maxAspectRatio > 0) {
|
||||
final float aspectRatio = (0.5f + Math.max(appWidth, appHeight))
|
||||
/ Math.min(appWidth, appHeight);
|
||||
if (aspectRatio >= info.maxAspectRatio) {
|
||||
// The current size has reached the max aspect ratio.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (info.minAspectRatio > 0) {
|
||||
// The activity should have at least the min aspect ratio, so this checks if the
|
||||
// container still has available space to provide larger aspect ratio.
|
||||
final float containerAspectRatio =
|
||||
(0.5f + Math.max(containerAppWidth, containerAppHeight))
|
||||
/ Math.min(containerAppWidth, containerAppHeight);
|
||||
if (containerAspectRatio <= info.minAspectRatio) {
|
||||
// The long side has reached the parent.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @return The horizontal offset of putting the content in the center of viewport. */
|
||||
@@ -7305,7 +7443,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
final Task rootTask = getRootTask();
|
||||
final float minAspectRatio = info.minAspectRatio;
|
||||
|
||||
if (task == null || rootTask == null || (inMultiWindowMode() && !shouldUseSizeCompatMode())
|
||||
if (task == null || rootTask == null
|
||||
|| (inMultiWindowMode() && !shouldCreateCompatDisplayInsets())
|
||||
|| (maxAspectRatio == 0 && minAspectRatio == 0)
|
||||
|| isInVrUiMode(getConfiguration())) {
|
||||
// We don't enforce aspect ratio if the activity task is in multiwindow unless it
|
||||
@@ -7443,8 +7582,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
if (displayChanged) {
|
||||
mLastReportedDisplayId = newDisplayId;
|
||||
}
|
||||
// TODO(b/36505427): Is there a better place to do this?
|
||||
updateSizeCompatMode();
|
||||
|
||||
// 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
|
||||
@@ -7723,11 +7860,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// Reset the existing override configuration so it can be updated according to the latest
|
||||
// configuration.
|
||||
clearSizeCompatMode();
|
||||
if (mVisibleRequested) {
|
||||
// Configuration will be ensured when becoming visible, so if it is already visible,
|
||||
// then the manual update is needed.
|
||||
updateSizeCompatMode();
|
||||
}
|
||||
|
||||
if (!attachedToProcess()) {
|
||||
return;
|
||||
@@ -8134,8 +8266,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
private final int mHeight;
|
||||
/** Whether the {@link Task} windowingMode represents a floating window*/
|
||||
final boolean mIsFloating;
|
||||
/** Whether the {@link Task} is letterboxed when the unresizable activity is first shown. */
|
||||
final boolean mIsTaskLetterboxed;
|
||||
/**
|
||||
* Whether is letterboxed because of fixed orientation when the unresizable activity is
|
||||
* first shown.
|
||||
*/
|
||||
final boolean mIsInFixedOrientationLetterbox;
|
||||
/**
|
||||
* The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
|
||||
* is used to compute the appBounds.
|
||||
@@ -8149,7 +8284,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
final Rect[] mStableInsets = new Rect[4];
|
||||
|
||||
/** Constructs the environment to simulate the bounds behavior of the given container. */
|
||||
CompatDisplayInsets(DisplayContent display, ActivityRecord container) {
|
||||
CompatDisplayInsets(DisplayContent display, ActivityRecord container,
|
||||
@Nullable Rect fixedOrientationBounds) {
|
||||
mIsFloating = container.getWindowConfiguration().tasksAreFloating();
|
||||
if (mIsFloating) {
|
||||
final Rect containerBounds = container.getWindowConfiguration().getBounds();
|
||||
@@ -8162,24 +8298,34 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
mNonDecorInsets[rotation] = emptyRect;
|
||||
mStableInsets[rotation] = emptyRect;
|
||||
}
|
||||
mIsTaskLetterboxed = false;
|
||||
mIsInFixedOrientationLetterbox = false;
|
||||
return;
|
||||
}
|
||||
|
||||
final Task task = container.getTask();
|
||||
mIsTaskLetterboxed = task != null && task.isTaskLetterboxed();
|
||||
|
||||
mIsInFixedOrientationLetterbox = fixedOrientationBounds != null;
|
||||
|
||||
// Store the bounds of the Task for the non-resizable activity to use in size compat
|
||||
// mode so that the activity will not be resized regardless the windowing mode it is
|
||||
// currently in.
|
||||
final WindowContainer filledContainer = task != null ? task : display;
|
||||
final Point dimensions = getRotationZeroDimensions(filledContainer);
|
||||
// When an activity needs to be letterboxed because of fixed orientation, use fixed
|
||||
// orientation bounds instead of task bounds since the activity will be displayed
|
||||
// within these even if it is in size compat mode.
|
||||
final Rect filledContainerBounds = mIsInFixedOrientationLetterbox
|
||||
? fixedOrientationBounds
|
||||
: task != null ? task.getBounds() : display.getBounds();
|
||||
final int filledContainerRotation = task != null
|
||||
? task.getConfiguration().windowConfiguration.getRotation()
|
||||
: display.getConfiguration().windowConfiguration.getRotation();
|
||||
final Point dimensions = getRotationZeroDimensions(
|
||||
filledContainerBounds, filledContainerRotation);
|
||||
mWidth = dimensions.x;
|
||||
mHeight = dimensions.y;
|
||||
|
||||
// Bounds of the filled container if it doesn't fill the display.
|
||||
final Rect unfilledContainerBounds =
|
||||
filledContainer.getBounds().equals(display.getBounds()) ? null : new Rect();
|
||||
filledContainerBounds.equals(display.getBounds()) ? null : new Rect();
|
||||
final DisplayPolicy policy = display.getDisplayPolicy();
|
||||
for (int rotation = 0; rotation < 4; rotation++) {
|
||||
mNonDecorInsets[rotation] = new Rect();
|
||||
@@ -8199,9 +8345,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// The insets is based on the display, but the container may be smaller than the
|
||||
// display, so update the insets to exclude parts that are not intersected with the
|
||||
// container.
|
||||
unfilledContainerBounds.set(filledContainer.getBounds());
|
||||
unfilledContainerBounds.set(filledContainerBounds);
|
||||
display.rotateBounds(
|
||||
filledContainer.getConfiguration().windowConfiguration.getRotation(),
|
||||
filledContainerRotation,
|
||||
rotation,
|
||||
unfilledContainerBounds);
|
||||
updateInsetsForBounds(unfilledContainerBounds, dw, dh, mNonDecorInsets[rotation]);
|
||||
@@ -8214,9 +8360,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
* the display is rotated, we can calculate the bounds by rotating the dimensions.
|
||||
* @see #getBoundsByRotation
|
||||
*/
|
||||
private static Point getRotationZeroDimensions(WindowContainer container) {
|
||||
final Rect bounds = container.getBounds();
|
||||
final int rotation = container.getConfiguration().windowConfiguration.getRotation();
|
||||
private static Point getRotationZeroDimensions(final Rect bounds, int rotation) {
|
||||
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
|
||||
final int width = bounds.width();
|
||||
final int height = bounds.height();
|
||||
|
||||
@@ -35,7 +35,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.activityTypeToString;
|
||||
import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
|
||||
import static android.app.WindowConfiguration.windowingModeToString;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
@@ -148,7 +147,6 @@ import static com.android.server.wm.WindowContainerChildProto.TASK;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
import static com.android.server.wm.WindowManagerService.MIN_TASK_LETTERBOX_ASPECT_RATIO;
|
||||
import static com.android.server.wm.WindowManagerService.dipToPixel;
|
||||
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_BEFORE_ANIM;
|
||||
|
||||
@@ -597,10 +595,6 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
@Nullable
|
||||
private ActivityRecord mResumedActivity = null;
|
||||
|
||||
/** Last activity that is used to compute the Task bounds. */
|
||||
@Nullable
|
||||
private ActivityRecord mLastTaskBoundsComputeActivity;
|
||||
|
||||
private boolean mForceShowForAllUsers;
|
||||
|
||||
/** When set, will force the task to report as invisible. */
|
||||
@@ -1496,11 +1490,6 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
}
|
||||
|
||||
void cleanUpActivityReferences(ActivityRecord r) {
|
||||
// mLastTaskBoundsComputeActivity is set at leaf Task
|
||||
if (mLastTaskBoundsComputeActivity == r) {
|
||||
mLastTaskBoundsComputeActivity = null;
|
||||
}
|
||||
|
||||
// mPausingActivity is set at leaf task
|
||||
if (mPausingActivity != null && mPausingActivity == r) {
|
||||
mPausingActivity = null;
|
||||
@@ -2863,7 +2852,6 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
|
||||
private void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig,
|
||||
Rect previousBounds) {
|
||||
mLastTaskBoundsComputeActivity = getTopNonFinishingActivity(false /* includeOverlays */);
|
||||
|
||||
int windowingMode =
|
||||
getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
|
||||
@@ -2877,7 +2865,8 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
getResolvedOverrideConfiguration().windowConfiguration.getBounds();
|
||||
|
||||
if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
|
||||
computeFullscreenBounds(outOverrideBounds, newParentConfig);
|
||||
// Use empty bounds to indicate "fill parent".
|
||||
outOverrideBounds.setEmpty();
|
||||
// The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
|
||||
// the parent or display is smaller than the size, the content may be cropped.
|
||||
return;
|
||||
@@ -2888,21 +2877,6 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
computeFreeformBounds(outOverrideBounds, newParentConfig);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSplitScreenWindowingMode(windowingMode)
|
||||
|| windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
|
||||
// This is to compute whether the task should be letterboxed to handle non-resizable app
|
||||
// in multi window. There is no split screen only logic.
|
||||
computeLetterboxBounds(outOverrideBounds, newParentConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}. */
|
||||
@VisibleForTesting
|
||||
void computeFullscreenBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) {
|
||||
// In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
|
||||
outBounds.setEmpty();
|
||||
computeLetterboxBounds(outBounds, newParentConfig);
|
||||
}
|
||||
|
||||
/** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FREEFORM}. */
|
||||
@@ -2934,94 +2908,6 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes bounds (letterbox or pillarbox) when the parent doesn't handle the orientation
|
||||
* change and the requested orientation is different from the parent.
|
||||
*/
|
||||
private void computeLetterboxBounds(@NonNull Rect outBounds,
|
||||
@NonNull Configuration newParentConfig) {
|
||||
if (handlesOrientationChangeFromDescendant()) {
|
||||
// No need to letterbox at task level. Display will handle fixed-orientation requests.
|
||||
return;
|
||||
}
|
||||
|
||||
final int parentOrientation = newParentConfig.orientation;
|
||||
// Use the top activity as the reference of orientation. Don't include overlays because
|
||||
// it is usually not the actual content or just temporarily shown.
|
||||
// E.g. ForcedResizableInfoActivity.
|
||||
final ActivityRecord refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
|
||||
|
||||
// If the task or the reference activity requires a different orientation (either by
|
||||
// override or activityInfo), make it fit the available bounds by scaling down its bounds.
|
||||
final int overrideOrientation = getRequestedOverrideConfiguration().orientation;
|
||||
final int forcedOrientation =
|
||||
(overrideOrientation != ORIENTATION_UNDEFINED || refActivity == null)
|
||||
? overrideOrientation : refActivity.getRequestedConfigurationOrientation();
|
||||
if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ActivityRecord.CompatDisplayInsets compatDisplayInsets =
|
||||
refActivity == null ? null : refActivity.getCompatDisplayInsets();
|
||||
if (compatDisplayInsets != null && !compatDisplayInsets.mIsTaskLetterboxed) {
|
||||
// App prefers to keep its original size.
|
||||
// If the size compat is from previous task letterboxing, we may want to have task
|
||||
// letterbox again, otherwise it will show the size compat restart button even if the
|
||||
// restart bounds will be the same.
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Adjust the Task letterbox bounds to fit the app request aspect ratio in order to use the
|
||||
// extra available space.
|
||||
if (refActivity != null) {
|
||||
final float maxAspectRatio = refActivity.info.maxAspectRatio;
|
||||
final float minAspectRatio = refActivity.info.minAspectRatio;
|
||||
if (aspect > maxAspectRatio && maxAspectRatio != 0) {
|
||||
aspect = maxAspectRatio;
|
||||
} else if (aspect < minAspectRatio) {
|
||||
aspect = minAspectRatio;
|
||||
}
|
||||
}
|
||||
|
||||
// Override from config_letterboxAspectRatio or via ADB with set-letterbox-aspect-ratio.
|
||||
final float letterboxAspectRatioOverride = mWmService.getTaskLetterboxAspectRatio();
|
||||
// Activity min/max aspect ratio restrictions will be respected by the activity-level
|
||||
// letterboxing (size-compat mode). Therefore this override can control the maximum screen
|
||||
// area that can be occupied by the app in the letterbox mode.
|
||||
aspect = letterboxAspectRatioOverride > MIN_TASK_LETTERBOX_ASPECT_RATIO
|
||||
? letterboxAspectRatioOverride : aspect;
|
||||
|
||||
// Store the current bounds to be able to revert to size compat mode values below if needed.
|
||||
mTmpFullBounds.set(outBounds);
|
||||
if (forcedOrientation == ORIENTATION_LANDSCAPE) {
|
||||
final int height = (int) Math.rint(parentWidth / aspect);
|
||||
final int top = parentBounds.centerY() - height / 2;
|
||||
outBounds.set(parentBounds.left, top, parentBounds.right, top + height);
|
||||
} else {
|
||||
final int width = (int) Math.rint(parentHeight / aspect);
|
||||
final int left = parentBounds.centerX() - width / 2;
|
||||
outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
|
||||
}
|
||||
|
||||
if (compatDisplayInsets != null) {
|
||||
compatDisplayInsets.getBoundsByRotation(
|
||||
mTmpBounds, newParentConfig.windowConfiguration.getRotation());
|
||||
if (outBounds.width() != mTmpBounds.width()
|
||||
|| outBounds.height() != mTmpBounds.height()) {
|
||||
// The app shouldn't be resized, we only do task letterboxing if the compat bounds
|
||||
// is also from the same task letterbox. Otherwise, clear the task bounds to show
|
||||
// app in size compat mode.
|
||||
outBounds.set(mTmpFullBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rect updateOverrideConfigurationFromLaunchBounds() {
|
||||
// If the task is controlled by another organized task, do not set override
|
||||
// configurations and let its parent (organized task) to control it;
|
||||
@@ -3036,11 +2922,6 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ActivityRecord getLastTaskBoundsComputeActivity() {
|
||||
return mLastTaskBoundsComputeActivity;
|
||||
}
|
||||
|
||||
/** Updates the task's bounds and override configuration to match what is expected for the
|
||||
* input root task. */
|
||||
void updateOverrideConfigurationForRootTask(Task inRootTask) {
|
||||
@@ -3939,12 +3820,6 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
|| activityType == ACTIVITY_TYPE_ASSISTANT;
|
||||
}
|
||||
|
||||
boolean isTaskLetterboxed() {
|
||||
// No letterbox for multi window root task
|
||||
return !matchParentBounds()
|
||||
&& (getWindowingMode() == WINDOWING_MODE_FULLSCREEN || !isRootTask());
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean fillsParent() {
|
||||
// From the perspective of policy, we still want to report that this task fills parent
|
||||
|
||||
@@ -3827,13 +3827,21 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
/** @return true when the window should be letterboxed. */
|
||||
boolean isLetterboxedAppWindow() {
|
||||
// Fullscreen mode but doesn't fill display area.
|
||||
return (!inMultiWindowMode() && !matchesDisplayAreaBounds())
|
||||
// Activity in size compat.
|
||||
|| (mActivityRecord != null && mActivityRecord.inSizeCompatMode())
|
||||
// Task letterboxed.
|
||||
|| (getTask() != null && getTask().isTaskLetterboxed())
|
||||
// Letterboxed for display cutout.
|
||||
|| isLetterboxedForDisplayCutout();
|
||||
if (!inMultiWindowMode() && !matchesDisplayAreaBounds()) {
|
||||
return true;
|
||||
}
|
||||
if (mActivityRecord != null) {
|
||||
// Activity in size compat.
|
||||
if (mActivityRecord.inSizeCompatMode()) {
|
||||
return true;
|
||||
}
|
||||
// Letterbox for fixed orientation.
|
||||
if (mActivityRecord.isLetterboxedForFixedOrientationAndAspectRatio()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Letterboxed for display cutout.
|
||||
return isLetterboxedForDisplayCutout();
|
||||
}
|
||||
|
||||
/** Returns {@code true} if the window is letterboxed for the display cutout. */
|
||||
|
||||
@@ -555,9 +555,10 @@ public class ActivityRecordTests extends WindowTestsBase {
|
||||
activity.setRequestedOrientation(
|
||||
isScreenPortrait ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);
|
||||
|
||||
// Asserts it has orientation derived from bounds.
|
||||
assertEquals(isScreenPortrait ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT,
|
||||
// Asserts it has orientation derived requested orientation (fixed orientation letterbox).
|
||||
assertEquals(isScreenPortrait ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE,
|
||||
activity.getConfiguration().orientation);
|
||||
assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -171,7 +171,7 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
|
||||
final Rect activityBounds = new Rect(mFirstActivity.getBounds());
|
||||
|
||||
// DAG is portrait (860x1200), so Task and Activity fill DAG.
|
||||
assertThat(mFirstTask.isTaskLetterboxed()).isFalse();
|
||||
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
|
||||
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
|
||||
assertThat(taskBounds).isEqualTo(dagBounds);
|
||||
assertThat(activityBounds).isEqualTo(taskBounds);
|
||||
@@ -194,8 +194,8 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
|
||||
final Rect activityConfigBounds =
|
||||
new Rect(mFirstActivity.getConfiguration().windowConfiguration.getBounds());
|
||||
|
||||
// DAG is landscape (1200x860), Task fills parent
|
||||
assertThat(mFirstTask.isTaskLetterboxed()).isFalse();
|
||||
// DAG is landscape (1200x860), no fixed orientation letterbox
|
||||
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
|
||||
assertThat(mFirstActivity.inSizeCompatMode()).isTrue();
|
||||
assertThat(newDagBounds.width()).isEqualTo(dagBounds.height());
|
||||
assertThat(newDagBounds.height()).isEqualTo(dagBounds.width());
|
||||
@@ -211,7 +211,7 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchLandscapeApp_taskIsLetterboxInDisplayAreaGroup() {
|
||||
public void testLaunchLandscapeApp_activityIsLetterboxForFixedOrientationInDisplayAreaGroup() {
|
||||
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
|
||||
mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
|
||||
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
|
||||
@@ -221,17 +221,18 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
|
||||
final Rect taskBounds = new Rect(mFirstTask.getBounds());
|
||||
final Rect activityBounds = new Rect(mFirstActivity.getBounds());
|
||||
|
||||
// DAG is portrait (860x1200), so Task is letterbox (860x[860x860/1200=616])
|
||||
assertThat(mFirstTask.isTaskLetterboxed()).isTrue();
|
||||
// DAG is portrait (860x1200), and activity is letterboxed for fixed orientation
|
||||
// (860x[860x860/1200=616]). Task fills DAG.
|
||||
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isTrue();
|
||||
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
|
||||
assertThat(taskBounds.width()).isEqualTo(dagBounds.width());
|
||||
assertThat(taskBounds.height())
|
||||
assertThat(taskBounds).isEqualTo(dagBounds);
|
||||
assertThat(activityBounds.width()).isEqualTo(dagBounds.width());
|
||||
assertThat(activityBounds.height())
|
||||
.isEqualTo(dagBounds.width() * dagBounds.width() / dagBounds.height());
|
||||
assertThat(activityBounds).isEqualTo(taskBounds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchLandscapeApp_taskLetterboxBecomesActivityLetterboxAfterRotation() {
|
||||
public void testLaunchLandscapeApp_fixedOrientationLetterboxBecomesSizeCompatAfterRotation() {
|
||||
mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
|
||||
mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
|
||||
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
|
||||
@@ -245,9 +246,8 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
|
||||
final Rect newTaskBounds = new Rect(mFirstTask.getBounds());
|
||||
final Rect newActivityBounds = new Rect(mFirstActivity.getBounds());
|
||||
|
||||
// DAG is landscape (1200x860), Task fills parent
|
||||
// Task letterbox size
|
||||
assertThat(mFirstTask.isTaskLetterboxed()).isFalse();
|
||||
// DAG is landscape (1200x860), no fixed orientation letterbox
|
||||
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
|
||||
assertThat(mFirstActivity.inSizeCompatMode()).isTrue();
|
||||
assertThat(newDagBounds.width()).isEqualTo(dagBounds.height());
|
||||
assertThat(newDagBounds.height()).isEqualTo(dagBounds.width());
|
||||
@@ -311,7 +311,7 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResizableFixedOrientationApp_taskLevelLetterboxing() {
|
||||
public void testResizableFixedOrientationApp_fixedOrientationLetterboxing() {
|
||||
mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
|
||||
mSecondRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
|
||||
|
||||
@@ -324,7 +324,7 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
|
||||
assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_LANDSCAPE);
|
||||
assertThat(mFirstRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
|
||||
assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
|
||||
assertThat(mFirstTask.isTaskLetterboxed()).isFalse();
|
||||
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
|
||||
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
|
||||
|
||||
// Launch portrait on second DAG
|
||||
@@ -336,13 +336,13 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
|
||||
assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
|
||||
assertThat(mSecondRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
|
||||
assertThat(mSecondActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
|
||||
assertThat(mSecondTask.isTaskLetterboxed()).isFalse();
|
||||
assertThat(mSecondActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
|
||||
assertThat(mSecondActivity.inSizeCompatMode()).isFalse();
|
||||
|
||||
// First activity is letterboxed in portrait as requested.
|
||||
assertThat(mFirstRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
|
||||
assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
|
||||
assertThat(mFirstTask.isTaskLetterboxed()).isTrue();
|
||||
assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isTrue();
|
||||
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
|
||||
import static android.view.Surface.ROTATION_180;
|
||||
import static android.view.Surface.ROTATION_270;
|
||||
import static android.view.Surface.ROTATION_90;
|
||||
@@ -43,7 +44,6 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.same;
|
||||
@@ -126,6 +126,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
// Put app window into freeform and then make it a compat app.
|
||||
final Rect bounds = new Rect(100, 100, 400, 600);
|
||||
mTask.setBounds(bounds);
|
||||
|
||||
prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
|
||||
assertEquals(bounds, mActivity.getBounds());
|
||||
|
||||
@@ -194,12 +195,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
new TestDisplayContent.Builder(mAtm, 1000, 2000)
|
||||
.setDensityDpi(200).build();
|
||||
|
||||
mActivity = new ActivityBuilder(mAtm)
|
||||
.setTask(mTask)
|
||||
.setResizeMode(RESIZE_MODE_UNRESIZEABLE)
|
||||
.setMaxAspectRatio(1.5f)
|
||||
.build();
|
||||
mActivity.mVisibleRequested = true;
|
||||
prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);
|
||||
|
||||
final Rect originalBounds = new Rect(mActivity.getBounds());
|
||||
final int originalDpi = mActivity.getConfiguration().densityDpi;
|
||||
@@ -566,18 +562,18 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
.setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
|
||||
.setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
|
||||
.build();
|
||||
assertTrue(activity.shouldUseSizeCompatMode());
|
||||
assertTrue(activity.shouldCreateCompatDisplayInsets());
|
||||
|
||||
// The non-resizable activity should not be size compat because it is on a resizable task
|
||||
// in multi-window mode.
|
||||
mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
|
||||
assertFalse(activity.shouldUseSizeCompatMode());
|
||||
assertFalse(activity.shouldCreateCompatDisplayInsets());
|
||||
|
||||
// The non-resizable activity should not be size compat because the display support
|
||||
// changing windowing mode from fullscreen to freeform.
|
||||
mTask.mDisplayContent.setDisplayWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
|
||||
mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
|
||||
assertFalse(activity.shouldUseSizeCompatMode());
|
||||
assertFalse(activity.shouldCreateCompatDisplayInsets());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -597,7 +593,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
SizeCompatTests.class.getName()))
|
||||
.setUid(android.os.Process.myUid())
|
||||
.build();
|
||||
assertFalse(activity.shouldUseSizeCompatMode());
|
||||
assertFalse(activity.shouldCreateCompatDisplayInsets());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -653,7 +649,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayIgnoreOrientationRequest_fixedOrientationAppLaunchedInTaskLetterbox() {
|
||||
public void testDisplayIgnoreOrientationRequest_fixedOrientationAppLaunchedLetterbox() {
|
||||
// Set up a display in landscape and ignoring orientation request.
|
||||
setUpDisplaySizeWithApp(2800, 1400);
|
||||
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
|
||||
@@ -662,7 +658,6 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
|
||||
|
||||
final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
|
||||
final Rect taskBounds = new Rect(mTask.getBounds());
|
||||
final Rect activityBounds = new Rect(mActivity.getBounds());
|
||||
|
||||
// Display shouldn't be rotated.
|
||||
@@ -670,19 +665,19 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
mActivity.mDisplayContent.getLastOrientation());
|
||||
assertTrue(displayBounds.width() > displayBounds.height());
|
||||
|
||||
// App should launch in task level letterboxing.
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
// App should launch in fixed orientation letterbox.
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(mActivity.inSizeCompatMode());
|
||||
assertEquals(taskBounds, activityBounds);
|
||||
|
||||
// Task bounds should be 700x1400 with the ratio as the display.
|
||||
assertEquals(displayBounds.height(), taskBounds.height());
|
||||
// Activity bounds should be 700x1400 with the ratio as the display.
|
||||
assertEquals(displayBounds.height(), activityBounds.height());
|
||||
assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
|
||||
taskBounds.width());
|
||||
activityBounds.width());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayIgnoreOrientationRequest_taskLetterboxBecameSizeCompatAfterRotate() {
|
||||
public void
|
||||
testDisplayIgnoreOrientationRequest_orientationLetterboxBecameSizeCompatAfterRotate() {
|
||||
// Set up a display in landscape and ignoring orientation request.
|
||||
setUpDisplaySizeWithApp(2800, 1400);
|
||||
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
|
||||
@@ -700,7 +695,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
assertTrue(displayBounds.width() < displayBounds.height());
|
||||
|
||||
// App should be in size compat.
|
||||
assertFalse(mTask.isTaskLetterboxed());
|
||||
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertScaled();
|
||||
assertEquals(activityBounds.width(), newActivityBounds.width());
|
||||
assertEquals(activityBounds.height(), newActivityBounds.height());
|
||||
@@ -719,7 +714,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
Rect activityBounds = new Rect(mActivity.getBounds());
|
||||
|
||||
// App should launch in fullscreen.
|
||||
assertFalse(mTask.isTaskLetterboxed());
|
||||
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(mActivity.inSizeCompatMode());
|
||||
assertEquals(displayBounds, activityBounds);
|
||||
|
||||
@@ -731,7 +726,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
assertTrue(displayBounds.width() > displayBounds.height());
|
||||
|
||||
// App should be in size compat.
|
||||
assertFalse(mTask.isTaskLetterboxed());
|
||||
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertScaled();
|
||||
|
||||
// App bounds should be 700x1400 with the ratio as the display.
|
||||
@@ -741,7 +736,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisplayIgnoreOrientationRequest_newLaunchedOrientationAppInTaskLetterbox() {
|
||||
public void testDisplayIgnoreOrientationRequest_newLaunchedOrientationAppInLetterbox() {
|
||||
// Set up a display in landscape and ignoring orientation request.
|
||||
setUpDisplaySizeWithApp(2800, 1400);
|
||||
final DisplayContent display = mActivity.mDisplayContent;
|
||||
@@ -750,7 +745,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
// Portrait fixed app without max aspect.
|
||||
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
|
||||
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(mActivity.inSizeCompatMode());
|
||||
|
||||
// Launch another portrait fixed app.
|
||||
@@ -765,19 +760,19 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
// Update with new activity requested orientation and recompute bounds with no previous
|
||||
// size compat cache.
|
||||
verify(mTask).onDescendantOrientationChanged(same(newActivity));
|
||||
verify(mTask).computeFullscreenBounds(any(), any());
|
||||
|
||||
final Rect displayBounds = new Rect(display.getBounds());
|
||||
final Rect taskBounds = new Rect(mTask.getBounds());
|
||||
final Rect newActivityBounds = new Rect(newActivity.getBounds());
|
||||
|
||||
// Task and app bounds should be 700x1400 with the ratio as the display.
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
// Task and display bounds should be equal while activity should be letterboxed and
|
||||
// has 700x1400 bounds with the ratio as the display.
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(newActivity.inSizeCompatMode());
|
||||
assertEquals(taskBounds, newActivityBounds);
|
||||
assertEquals(displayBounds.height(), taskBounds.height());
|
||||
assertEquals(taskBounds, displayBounds);
|
||||
assertEquals(displayBounds.height(), newActivityBounds.height());
|
||||
assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
|
||||
taskBounds.width());
|
||||
newActivityBounds.width());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -790,7 +785,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
// Portrait fixed app without max aspect.
|
||||
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
|
||||
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(mActivity.inSizeCompatMode());
|
||||
|
||||
// Launch another portrait fixed app with max aspect ratio as 1.3.
|
||||
@@ -806,21 +801,20 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
// Update with new activity requested orientation and recompute bounds with no previous
|
||||
// size compat cache.
|
||||
verify(mTask).onDescendantOrientationChanged(same(newActivity));
|
||||
verify(mTask).computeFullscreenBounds(any(), any());
|
||||
|
||||
final Rect displayBounds = new Rect(display.getBounds());
|
||||
final Rect taskBounds = new Rect(mTask.getBounds());
|
||||
final Rect newActivityBounds = new Rect(newActivity.getBounds());
|
||||
|
||||
// Task bounds should be (1400 / 1.3 = 1076)x1400 with the app requested ratio.
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
assertEquals(displayBounds.height(), taskBounds.height());
|
||||
assertEquals((long) Math.rint(taskBounds.height() / newActivity.info.maxAspectRatio),
|
||||
taskBounds.width());
|
||||
// Task bounds should fill parent bounds.
|
||||
assertEquals(displayBounds, taskBounds);
|
||||
|
||||
// App bounds should be fullscreen in Task bounds.
|
||||
// Activity bounds should be (1400 / 1.3 = 1076)x1400 with the app requested ratio.
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(newActivity.inSizeCompatMode());
|
||||
assertEquals(taskBounds, newActivityBounds);
|
||||
assertEquals(displayBounds.height(), newActivityBounds.height());
|
||||
assertEquals((long) Math.rint(newActivityBounds.height() / newActivity.info.maxAspectRatio),
|
||||
newActivityBounds.width());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -834,26 +828,23 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
|
||||
clearInvocations(mActivity);
|
||||
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(mActivity.inSizeCompatMode());
|
||||
assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
|
||||
|
||||
// Rotate display to portrait.
|
||||
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
|
||||
|
||||
// App should be in size compat.
|
||||
assertFalse(mTask.isTaskLetterboxed());
|
||||
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertScaled();
|
||||
assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
|
||||
|
||||
final Rect activityBounds = new Rect(mActivity.getBounds());
|
||||
mTask.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */);
|
||||
|
||||
// App still in size compat, and the bounds don't change.
|
||||
verify(mActivity, never()).clearSizeCompatMode();
|
||||
assertFalse(mTask.isTaskLetterboxed());
|
||||
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertScaled();
|
||||
assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
|
||||
assertEquals(activityBounds, mActivity.getBounds());
|
||||
}
|
||||
|
||||
@@ -867,22 +858,22 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
// Portrait fixed app.
|
||||
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
|
||||
|
||||
// In Task letterbox
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
// In fixed orientation letterbox
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(mActivity.inSizeCompatMode());
|
||||
|
||||
// Rotate display to portrait.
|
||||
rotateDisplay(display, ROTATION_90);
|
||||
|
||||
// App should be in size compat.
|
||||
assertFalse(mTask.isTaskLetterboxed());
|
||||
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertScaled();
|
||||
|
||||
// Rotate display to landscape.
|
||||
rotateDisplay(display, ROTATION_180);
|
||||
|
||||
// In Task letterbox
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(mActivity.inSizeCompatMode());
|
||||
}
|
||||
|
||||
@@ -898,22 +889,22 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
// Landscape fixed app.
|
||||
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_LANDSCAPE);
|
||||
|
||||
// In Task letterbox
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
// In fixed orientation letterbox
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(mActivity.inSizeCompatMode());
|
||||
|
||||
// Rotate display to portrait.
|
||||
rotateDisplay(display, ROTATION_90);
|
||||
|
||||
// App should be in size compat.
|
||||
assertFalse(mTask.isTaskLetterboxed());
|
||||
assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertScaled();
|
||||
|
||||
// Rotate display to landscape.
|
||||
rotateDisplay(display, ROTATION_180);
|
||||
|
||||
// In Task letterbox
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
// In fixed orientation letterbox
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
assertFalse(mActivity.inSizeCompatMode());
|
||||
}
|
||||
|
||||
@@ -972,21 +963,21 @@ public class SizeCompatTests extends WindowTestsBase {
|
||||
addWindowToActivity(mActivity);
|
||||
mActivity.mRootWindowContainer.performSurfacePlacement();
|
||||
|
||||
// Split screen is also in portrait [1000,1400], so Task should be in letterbox, and
|
||||
// activity fills task.
|
||||
assertEquals(ORIENTATION_LANDSCAPE, mTask.getConfiguration().orientation);
|
||||
// Split screen is also in portrait [1000,1400], so activty should be in fixed orientation
|
||||
// letterbox.
|
||||
assertEquals(ORIENTATION_PORTRAIT, mTask.getConfiguration().orientation);
|
||||
assertEquals(ORIENTATION_LANDSCAPE, mActivity.getConfiguration().orientation);
|
||||
assertFitted();
|
||||
assertTrue(mTask.isTaskLetterboxed());
|
||||
assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
|
||||
|
||||
// Letterbox should fill the gap between the split screen and the letterboxed task.
|
||||
// Letterbox should fill the gap between the split screen and the letterboxed activity.
|
||||
final Rect primarySplitBounds = new Rect(organizer.mPrimary.getBounds());
|
||||
final Rect letterboxedTaskBounds = new Rect(mTask.getBounds());
|
||||
assertTrue(primarySplitBounds.contains(letterboxedTaskBounds));
|
||||
assertEquals(new Rect(letterboxedTaskBounds.left - primarySplitBounds.left,
|
||||
letterboxedTaskBounds.top - primarySplitBounds.top,
|
||||
primarySplitBounds.right - letterboxedTaskBounds.right,
|
||||
primarySplitBounds.bottom - letterboxedTaskBounds.bottom),
|
||||
final Rect letterboxedBounds = new Rect(mActivity.getBounds());
|
||||
assertTrue(primarySplitBounds.contains(letterboxedBounds));
|
||||
assertEquals(new Rect(letterboxedBounds.left - primarySplitBounds.left,
|
||||
letterboxedBounds.top - primarySplitBounds.top,
|
||||
primarySplitBounds.right - letterboxedBounds.right,
|
||||
primarySplitBounds.bottom - letterboxedBounds.bottom),
|
||||
mActivity.getLetterboxInsets());
|
||||
}
|
||||
|
||||
|
||||
@@ -266,8 +266,9 @@ public class TaskRecordTests extends WindowTestsBase {
|
||||
root.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
|
||||
assertEquals(root, task.getRootActivity());
|
||||
assertEquals(SCREEN_ORIENTATION_PORTRAIT, task.getRootActivity().getOrientation());
|
||||
assertThat(task.getBounds().width()).isLessThan(task.getBounds().height());
|
||||
assertEquals(fullScreenBounds.height(), task.getBounds().height());
|
||||
// Portrait orientation is enforced on activity level. Task should fill fullscreen bounds.
|
||||
assertThat(task.getBounds().height()).isLessThan(task.getBounds().width());
|
||||
assertEquals(fullScreenBounds, task.getBounds());
|
||||
|
||||
// Top activity gets used
|
||||
final ActivityRecord top = new ActivityBuilder(mAtm).setTask(task).setParentTask(stack)
|
||||
@@ -286,8 +287,11 @@ public class TaskRecordTests extends WindowTestsBase {
|
||||
// Fix the display orientation to portrait which is 90 degrees for the test display.
|
||||
dr.setUserRotation(USER_ROTATION_FREE, ROTATION_90);
|
||||
|
||||
assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
|
||||
assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
|
||||
// Fixed orientation request should be resolved on activity level. Task fills display
|
||||
// bounds.
|
||||
assertThat(task.getBounds().height()).isGreaterThan(task.getBounds().width());
|
||||
assertThat(top.getBounds().width()).isGreaterThan(top.getBounds().height());
|
||||
assertEquals(fullScreenBoundsPort, task.getBounds());
|
||||
|
||||
// in FREEFORM, no constraint
|
||||
final Rect freeformBounds = new Rect(display.getBounds());
|
||||
@@ -297,10 +301,11 @@ public class TaskRecordTests extends WindowTestsBase {
|
||||
task.setBounds(freeformBounds);
|
||||
assertEquals(freeformBounds, task.getBounds());
|
||||
|
||||
// FULLSCREEN letterboxes bounds
|
||||
// FULLSCREEN letterboxes bounds on activity level, no constraint on task level.
|
||||
stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
|
||||
assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
|
||||
assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
|
||||
assertThat(task.getBounds().height()).isGreaterThan(task.getBounds().width());
|
||||
assertThat(top.getBounds().width()).isGreaterThan(top.getBounds().height());
|
||||
assertEquals(fullScreenBoundsPort, task.getBounds());
|
||||
|
||||
// FREEFORM restores bounds as before
|
||||
stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
|
||||
@@ -327,9 +332,10 @@ public class TaskRecordTests extends WindowTestsBase {
|
||||
|
||||
assertEquals(fullScreenBounds, task.getBounds());
|
||||
|
||||
// Setting app to fixed portrait fits within parent
|
||||
// Setting app to fixed portrait fits within parent on activity level. Task fills parent.
|
||||
root.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
|
||||
assertThat(task.getBounds().width()).isLessThan(task.getBounds().height());
|
||||
assertThat(root.getBounds().width()).isLessThan(root.getBounds().height());
|
||||
assertEquals(task.getBounds(), fullScreenBounds);
|
||||
|
||||
assertEquals(SCREEN_ORIENTATION_PORTRAIT, task.getOrientation());
|
||||
}
|
||||
@@ -424,7 +430,8 @@ public class TaskRecordTests extends WindowTestsBase {
|
||||
// to the input bounds.
|
||||
final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
|
||||
final ActivityRecord.CompatDisplayInsets compatIntsets =
|
||||
new ActivityRecord.CompatDisplayInsets(display, activity);
|
||||
new ActivityRecord.CompatDisplayInsets(
|
||||
display, activity, /* fixedOrientationBounds= */ null);
|
||||
task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatIntsets);
|
||||
|
||||
assertEquals(largerLandscapeBounds, inOutConfig.windowConfiguration.getAppBounds());
|
||||
|
||||
@@ -257,24 +257,4 @@ public class TaskTests extends WindowTestsBase {
|
||||
task.resolveOverrideConfiguration(parentConfig);
|
||||
assertThat(resolvedOverride.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCleanUpActivityReferences_clearLastTaskBoundsComputeActivity() {
|
||||
final Task rootTask = createTaskStackOnDisplay(mDisplayContent);
|
||||
final Task leafTask = createTaskInStack(rootTask, 0 /* userId */);
|
||||
final ActivityRecord activity2 = createActivityRecord(mDisplayContent, leafTask);
|
||||
final ActivityRecord activity1 = createActivityRecord(mDisplayContent, leafTask);
|
||||
activity1.finishing = false;
|
||||
leafTask.resolveOverrideConfiguration(rootTask.getConfiguration());
|
||||
|
||||
assertEquals(activity1, leafTask.getLastTaskBoundsComputeActivity());
|
||||
|
||||
leafTask.cleanUpActivityReferences(activity2);
|
||||
|
||||
assertNotNull(leafTask.getLastTaskBoundsComputeActivity());
|
||||
|
||||
leafTask.cleanUpActivityReferences(activity1);
|
||||
|
||||
assertNull(leafTask.getLastTaskBoundsComputeActivity());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user