Merge "Update TaskLaunchParamsModifier.java to use DA instead DC" into sc-dev

This commit is contained in:
Chris Li
2021-03-04 01:26:06 +00:00
committed by Android (Google) Code Review
4 changed files with 206 additions and 102 deletions

View File

@@ -495,6 +495,21 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
return info;
}
/**
* Gets the stable bounds of the DisplayArea, which is the bounds excluding insets for
* navigation bar, cutout, and status bar.
*/
void getStableRect(Rect out) {
if (mDisplayContent == null) {
getBounds(out);
return;
}
// Intersect with the display stable bounds to get the DisplayArea stable bounds.
mDisplayContent.getStableRect(out);
out.intersect(getBounds());
}
@Override
public boolean providesMaxBounds() {
return true;

View File

@@ -2677,6 +2677,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mWmService.mDisplayWindowSettings.setForcedSize(this, width, height);
}
@Override
void getStableRect(Rect out) {
final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
out.set(state.getDisplayFrame());

View File

@@ -165,6 +165,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
// hasInitialBounds is set if either activity options or layout has specified bounds. If
// that's set we'll skip some adjustments later to avoid overriding the initial bounds.
boolean hasInitialBounds = false;
// hasInitialBoundsForSuggestedDisplayAreaInFreeformWindow is set if the outParams.mBounds
// is set with the suggestedDisplayArea. If it is set, but the eventual TaskDisplayArea is
// different, we should recalculating the bounds.
boolean hasInitialBoundsForSuggestedDisplayAreaInFreeformWindow = false;
final boolean canApplyFreeformPolicy = canApplyFreeformWindowPolicy(display, launchMode);
if (mSupervisor.canUseActivityOptionsLaunchBounds(options)
&& (canApplyFreeformPolicy || canApplyPipWindowPolicy(launchMode))) {
@@ -181,11 +185,12 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
if (DEBUG) appendLog("activity-options-fullscreen=" + outParams.mBounds);
} else if (layout != null && canApplyFreeformPolicy) {
mTmpBounds.set(currentParams.mBounds);
getLayoutBounds(display, root, layout, mTmpBounds);
getLayoutBounds(suggestedDisplayArea, root, layout, mTmpBounds);
if (!mTmpBounds.isEmpty()) {
launchMode = WINDOWING_MODE_FREEFORM;
outParams.mBounds.set(mTmpBounds);
hasInitialBounds = true;
hasInitialBoundsForSuggestedDisplayAreaInFreeformWindow = true;
if (DEBUG) appendLog("bounds-from-layout=" + outParams.mBounds);
} else {
if (DEBUG) appendLog("empty-window-layout");
@@ -241,6 +246,11 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
// such as orientation. Otherwise, the app is forcefully launched in maximized. The rest of
// this step is to define the default policy when there is no initial bounds or a fully
// resolved current params from callers.
// hasInitialBoundsForSuggestedDisplayAreaInFreeformDisplay is set if the outParams.mBounds
// is set with the suggestedDisplayArea. If it is set, but the eventual TaskDisplayArea is
// different, we should recalcuating the bounds.
boolean hasInitialBoundsForSuggestedDisplayAreaInFreeformDisplay = false;
if (display.inFreeformWindowingMode()) {
if (launchMode == WINDOWING_MODE_PINNED) {
if (DEBUG) appendLog("picture-in-picture");
@@ -248,8 +258,9 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
if (shouldLaunchUnresizableAppInFreeform(root, suggestedDisplayArea)) {
launchMode = WINDOWING_MODE_FREEFORM;
if (outParams.mBounds.isEmpty()) {
getTaskBounds(root, display, layout, launchMode, hasInitialBounds,
outParams.mBounds);
getTaskBounds(root, suggestedDisplayArea, layout, launchMode,
hasInitialBounds, outParams.mBounds);
hasInitialBoundsForSuggestedDisplayAreaInFreeformDisplay = true;
}
if (DEBUG) appendLog("unresizable-freeform");
} else {
@@ -288,6 +299,20 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
mTmpDisplayArea = displayArea;
return true;
});
// We may need to recalculate the bounds if the new TaskDisplayArea is different from
// the suggested one we used to calculate the bounds.
if (mTmpDisplayArea != null && mTmpDisplayArea != suggestedDisplayArea) {
if (hasInitialBoundsForSuggestedDisplayAreaInFreeformWindow) {
outParams.mBounds.setEmpty();
getLayoutBounds(mTmpDisplayArea, root, layout, outParams.mBounds);
hasInitialBounds = !outParams.mBounds.isEmpty();
} else if (hasInitialBoundsForSuggestedDisplayAreaInFreeformDisplay) {
outParams.mBounds.setEmpty();
getTaskBounds(root, mTmpDisplayArea, layout, launchMode,
hasInitialBounds, outParams.mBounds);
}
}
if (mTmpDisplayArea != null) {
taskDisplayArea = mTmpDisplayArea;
mTmpDisplayArea = null;
@@ -303,7 +328,6 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
if (phase == PHASE_DISPLAY_AREA) {
return RESULT_CONTINUE;
}
// TODO(b/152116619): Update the usages of display to use taskDisplayArea below.
// STEP 4: Determine final launch bounds based on resolved windowing mode and activity
// requested orientation. We set bounds to empty for fullscreen mode and keep bounds as is
@@ -313,13 +337,13 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
// We skip making adjustments if the params are fully resolved from previous results.
if (fullyResolvedCurrentParam) {
if (resolvedMode == WINDOWING_MODE_FREEFORM) {
// Make sure bounds are in the display if it's possibly in a different display/area.
// Make sure bounds are in the displayArea.
if (currentParams.mPreferredTaskDisplayArea != taskDisplayArea) {
adjustBoundsToFitInDisplay(display, outParams.mBounds);
adjustBoundsToFitInDisplayArea(taskDisplayArea, outParams.mBounds);
}
// Even though we want to keep original bounds, we still don't want it to stomp on
// an existing task.
adjustBoundsToAvoidConflictInDisplay(display, outParams.mBounds);
adjustBoundsToAvoidConflictInDisplayArea(taskDisplayArea, outParams.mBounds);
}
} else if (taskDisplayArea.inFreeformWindowingMode()) {
if (source != null && source.inFreeformWindowingMode()
@@ -328,9 +352,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
&& source.getDisplayArea() == taskDisplayArea) {
// Set bounds to be not very far from source activity.
cascadeBounds(source.getConfiguration().windowConfiguration.getBounds(),
display, outParams.mBounds);
taskDisplayArea, outParams.mBounds);
}
getTaskBounds(root, display, layout, resolvedMode, hasInitialBounds, outParams.mBounds);
getTaskBounds(root, taskDisplayArea, layout, resolvedMode, hasInitialBounds,
outParams.mBounds);
}
return RESULT_CONTINUE;
}
@@ -500,7 +525,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
&& launchMode == WINDOWING_MODE_PINNED;
}
private void getLayoutBounds(@NonNull DisplayContent display, @NonNull ActivityRecord root,
private void getLayoutBounds(@NonNull TaskDisplayArea displayArea, @NonNull ActivityRecord root,
@NonNull ActivityInfo.WindowLayout windowLayout, @NonNull Rect inOutBounds) {
final int verticalGravity = windowLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
final int horizontalGravity = windowLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
@@ -511,10 +536,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
// Use stable frame instead of raw frame to avoid launching freeform windows on top of
// stable insets, which usually are system widgets such as sysbar & navbar.
final Rect displayStableBounds = mTmpStableBounds;
display.getStableRect(displayStableBounds);
final int defaultWidth = displayStableBounds.width();
final int defaultHeight = displayStableBounds.height();
final Rect stableBounds = mTmpStableBounds;
displayArea.getStableRect(stableBounds);
final int defaultWidth = stableBounds.width();
final int defaultHeight = stableBounds.height();
int width;
int height;
@@ -525,7 +550,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
width = inOutBounds.width();
height = inOutBounds.height();
} else {
getTaskBounds(root, display, windowLayout, WINDOWING_MODE_FREEFORM,
getTaskBounds(root, displayArea, windowLayout, WINDOWING_MODE_FREEFORM,
/* hasInitialBounds */ false, inOutBounds);
width = inOutBounds.width();
height = inOutBounds.height();
@@ -571,7 +596,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
}
inOutBounds.set(0, 0, width, height);
inOutBounds.offset(displayStableBounds.left, displayStableBounds.top);
inOutBounds.offset(stableBounds.left, stableBounds.top);
final int xOffset = (int) (fractionOfHorizontalOffset * (defaultWidth - width));
final int yOffset = (int) (fractionOfVerticalOffset * (defaultHeight - height));
inOutBounds.offset(xOffset, yOffset);
@@ -582,13 +607,9 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
if (!mSupervisor.mService.mSupportsNonResizableMultiWindow || activity.isResizeable()) {
return false;
}
final DisplayContent display = displayArea.getDisplayContent();
if (display == null) {
return false;
}
final int displayOrientation = orientationFromBounds(displayArea.getBounds());
final int activityOrientation = resolveOrientation(activity, display,
final int activityOrientation = resolveOrientation(activity, displayArea,
displayArea.getBounds());
if (displayArea.getWindowingMode() == WINDOWING_MODE_FREEFORM
&& displayOrientation != activityOrientation) {
@@ -638,19 +659,19 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
return orientation;
}
private void cascadeBounds(@NonNull Rect srcBounds, @NonNull DisplayContent display,
private void cascadeBounds(@NonNull Rect srcBounds, @NonNull TaskDisplayArea displayArea,
@NonNull Rect outBounds) {
outBounds.set(srcBounds);
float density = (float) display.getConfiguration().densityDpi / DENSITY_DEFAULT;
float density = (float) displayArea.getConfiguration().densityDpi / DENSITY_DEFAULT;
final int defaultOffset = (int) (CASCADING_OFFSET_DP * density + 0.5f);
display.getBounds(mTmpBounds);
displayArea.getBounds(mTmpBounds);
final int dx = Math.min(defaultOffset, Math.max(0, mTmpBounds.right - srcBounds.right));
final int dy = Math.min(defaultOffset, Math.max(0, mTmpBounds.bottom - srcBounds.bottom));
outBounds.offset(dx, dy);
}
private void getTaskBounds(@NonNull ActivityRecord root, @NonNull DisplayContent display,
private void getTaskBounds(@NonNull ActivityRecord root, @NonNull TaskDisplayArea displayArea,
@NonNull ActivityInfo.WindowLayout layout, int resolvedMode, boolean hasInitialBounds,
@NonNull Rect inOutBounds) {
if (resolvedMode == WINDOWING_MODE_FULLSCREEN) {
@@ -669,7 +690,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
return;
}
final int orientation = resolveOrientation(root, display, inOutBounds);
final int orientation = resolveOrientation(root, displayArea, inOutBounds);
if (orientation != SCREEN_ORIENTATION_PORTRAIT
&& orientation != SCREEN_ORIENTATION_LANDSCAPE) {
throw new IllegalStateException(
@@ -678,7 +699,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
}
// First we get the default size we want.
getDefaultFreeformSize(display, layout, orientation, mTmpBounds);
getDefaultFreeformSize(displayArea, layout, orientation, mTmpBounds);
if (hasInitialBounds || sizeMatches(inOutBounds, mTmpBounds)) {
// We're here because either input parameters specified initial bounds, or the suggested
// bounds have the same size of the default freeform size. We should use the suggested
@@ -688,22 +709,24 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
if (DEBUG) appendLog("freeform-size-orientation-match=" + inOutBounds);
} else {
// Meh, orientation doesn't match. Let's rotate inOutBounds in-place.
centerBounds(display, inOutBounds.height(), inOutBounds.width(), inOutBounds);
centerBounds(displayArea, inOutBounds.height(), inOutBounds.width(),
inOutBounds);
if (DEBUG) appendLog("freeform-orientation-mismatch=" + inOutBounds);
}
} else {
// We are here either because there is no suggested bounds, or the suggested bounds is
// a cascade from source activity. We should use the default freeform size and center it
// to the center of suggested bounds (or the display if no suggested bounds). The
// default size might be too big to center to source activity bounds in display, so we
// may need to move it back to the display.
centerBounds(display, mTmpBounds.width(), mTmpBounds.height(), inOutBounds);
adjustBoundsToFitInDisplay(display, inOutBounds);
// to the center of suggested bounds (or the displayArea if no suggested bounds). The
// default size might be too big to center to source activity bounds in displayArea, so
// we may need to move it back to the displayArea.
centerBounds(displayArea, mTmpBounds.width(), mTmpBounds.height(),
inOutBounds);
adjustBoundsToFitInDisplayArea(displayArea, inOutBounds);
if (DEBUG) appendLog("freeform-size-mismatch=" + inOutBounds);
}
// Lastly we adjust bounds to avoid conflicts with other tasks as much as possible.
adjustBoundsToAvoidConflictInDisplay(display, inOutBounds);
adjustBoundsToAvoidConflictInDisplayArea(displayArea, inOutBounds);
}
private int convertOrientationToScreenOrientation(int orientation) {
@@ -717,13 +740,14 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
}
}
private int resolveOrientation(@NonNull ActivityRecord root, @NonNull DisplayContent display,
@NonNull Rect bounds) {
private int resolveOrientation(@NonNull ActivityRecord root,
@NonNull TaskDisplayArea displayArea, @NonNull Rect bounds) {
int orientation = resolveOrientation(root);
if (orientation == SCREEN_ORIENTATION_LOCKED) {
orientation = bounds.isEmpty()
? convertOrientationToScreenOrientation(display.getConfiguration().orientation)
? convertOrientationToScreenOrientation(
displayArea.getConfiguration().orientation)
: orientationFromBounds(bounds);
if (DEBUG) {
appendLog(bounds.isEmpty() ? "locked-orientation-from-display=" + orientation
@@ -743,19 +767,17 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
return orientation;
}
private void getDefaultFreeformSize(@NonNull DisplayContent display,
private void getDefaultFreeformSize(@NonNull TaskDisplayArea displayArea,
@NonNull ActivityInfo.WindowLayout layout, int orientation, @NonNull Rect bounds) {
// Default size, which is letterboxing/pillarboxing in display. That's to say the large
// dimension of default size is the small dimension of display size, and the small dimension
// of default size is calculated to keep the same aspect ratio as the display's. Here we use
// stable bounds of displays because that indicates the area that isn't occupied by system
// widgets (e.g. sysbar and navbar).
final Rect displayStableBounds = mTmpStableBounds;
display.getStableRect(displayStableBounds);
final int portraitHeight =
Math.min(displayStableBounds.width(), displayStableBounds.height());
final int otherDimension =
Math.max(displayStableBounds.width(), displayStableBounds.height());
// Default size, which is letterboxing/pillarboxing in displayArea. That's to say the large
// dimension of default size is the small dimension of displayArea size, and the small
// dimension of default size is calculated to keep the same aspect ratio as the
// displayArea's. Here we use stable bounds of displayArea because that indicates the area
// that isn't occupied by system widgets (e.g. sysbar and navbar).
final Rect stableBounds = mTmpStableBounds;
displayArea.getStableRect(stableBounds);
final int portraitHeight = Math.min(stableBounds.width(), stableBounds.height());
final int otherDimension = Math.max(stableBounds.width(), stableBounds.height());
final int portraitWidth = (portraitHeight * portraitHeight) / otherDimension;
final int defaultWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitHeight
: portraitWidth;
@@ -764,7 +786,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
// Get window size based on Nexus 5x screen, we assume that this is enough to show content
// of activities.
final float density = (float) display.getConfiguration().densityDpi / DENSITY_DEFAULT;
final float density = (float) displayArea.getConfiguration().densityDpi / DENSITY_DEFAULT;
final int phonePortraitWidth = (int) (DEFAULT_PORTRAIT_PHONE_WIDTH_DP * density + 0.5f);
final int phonePortraitHeight = (int) (DEFAULT_PORTRAIT_PHONE_HEIGHT_DP * density + 0.5f);
final int phoneWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? phonePortraitHeight
@@ -781,83 +803,83 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
final int height = Math.min(defaultHeight, Math.max(phoneHeight, layoutMinHeight));
bounds.set(0, 0, width, height);
bounds.offset(displayStableBounds.left, displayStableBounds.top);
bounds.offset(stableBounds.left, stableBounds.top);
}
/**
* Gets centered bounds of width x height. If inOutBounds is not empty, the result bounds
* centers at its center or display's app bounds center if inOutBounds is empty.
* centers at its center or displayArea's app bounds center if inOutBounds is empty.
*/
private void centerBounds(@NonNull DisplayContent display, int width, int height,
private void centerBounds(@NonNull TaskDisplayArea displayArea, int width, int height,
@NonNull Rect inOutBounds) {
if (inOutBounds.isEmpty()) {
display.getStableRect(inOutBounds);
displayArea.getStableRect(inOutBounds);
}
final int left = inOutBounds.centerX() - width / 2;
final int top = inOutBounds.centerY() - height / 2;
inOutBounds.set(left, top, left + width, top + height);
}
private void adjustBoundsToFitInDisplay(@NonNull DisplayContent display,
private void adjustBoundsToFitInDisplayArea(@NonNull TaskDisplayArea displayArea,
@NonNull Rect inOutBounds) {
final Rect displayStableBounds = mTmpStableBounds;
display.getStableRect(displayStableBounds);
final Rect stableBounds = mTmpStableBounds;
displayArea.getStableRect(stableBounds);
if (displayStableBounds.width() < inOutBounds.width()
|| displayStableBounds.height() < inOutBounds.height()) {
// There is no way for us to fit the bounds in the display without changing width
// or height. Just move the start to align with the display.
if (stableBounds.width() < inOutBounds.width()
|| stableBounds.height() < inOutBounds.height()) {
// There is no way for us to fit the bounds in the displayArea without changing width
// or height. Just move the start to align with the displayArea.
final int layoutDirection =
mSupervisor.mRootWindowContainer.getConfiguration().getLayoutDirection();
final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL
? displayStableBounds.right - inOutBounds.right + inOutBounds.left
: displayStableBounds.left;
inOutBounds.offsetTo(left, displayStableBounds.top);
? stableBounds.right - inOutBounds.right + inOutBounds.left
: stableBounds.left;
inOutBounds.offsetTo(left, stableBounds.top);
return;
}
final int dx;
if (inOutBounds.right > displayStableBounds.right) {
// Right edge is out of display.
dx = displayStableBounds.right - inOutBounds.right;
} else if (inOutBounds.left < displayStableBounds.left) {
// Left edge is out of display.
dx = displayStableBounds.left - inOutBounds.left;
if (inOutBounds.right > stableBounds.right) {
// Right edge is out of displayArea.
dx = stableBounds.right - inOutBounds.right;
} else if (inOutBounds.left < stableBounds.left) {
// Left edge is out of displayArea.
dx = stableBounds.left - inOutBounds.left;
} else {
// Vertical edges are all in display.
// Vertical edges are all in displayArea.
dx = 0;
}
final int dy;
if (inOutBounds.top < displayStableBounds.top) {
// Top edge is out of display.
dy = displayStableBounds.top - inOutBounds.top;
} else if (inOutBounds.bottom > displayStableBounds.bottom) {
// Bottom edge is out of display.
dy = displayStableBounds.bottom - inOutBounds.bottom;
if (inOutBounds.top < stableBounds.top) {
// Top edge is out of displayArea.
dy = stableBounds.top - inOutBounds.top;
} else if (inOutBounds.bottom > stableBounds.bottom) {
// Bottom edge is out of displayArea.
dy = stableBounds.bottom - inOutBounds.bottom;
} else {
// Horizontal edges are all in display.
// Horizontal edges are all in displayArea.
dy = 0;
}
inOutBounds.offset(dx, dy);
}
/**
* Adjusts input bounds to avoid conflict with existing tasks in the display.
* Adjusts input bounds to avoid conflict with existing tasks in the displayArea.
*
* If the input bounds conflict with existing tasks, this method scans the bounds in a series of
* directions to find a location where the we can put the bounds in display without conflict
* directions to find a location where the we can put the bounds in displayArea without conflict
* with any other tasks.
*
* It doesn't try to adjust bounds that's not fully in the given display.
* It doesn't try to adjust bounds that's not fully in the given displayArea.
*
* @param display the display which tasks are to check
* @param displayArea the displayArea which tasks are to check
* @param inOutBounds the bounds used to input initial bounds and output result bounds
*/
private void adjustBoundsToAvoidConflictInDisplay(@NonNull DisplayContent display,
private void adjustBoundsToAvoidConflictInDisplayArea(@NonNull TaskDisplayArea displayArea,
@NonNull Rect inOutBounds) {
final List<Rect> taskBoundsToCheck = new ArrayList<>();
display.forAllRootTasks(task -> {
displayArea.forAllRootTasks(task -> {
if (!task.inFreeformWindowingMode()) {
return;
}
@@ -866,28 +888,28 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
taskBoundsToCheck.add(task.getChildAt(j).getBounds());
}
}, false /* traverseTopToBottom */);
adjustBoundsToAvoidConflict(display.getBounds(), taskBoundsToCheck, inOutBounds);
adjustBoundsToAvoidConflict(displayArea.getBounds(), taskBoundsToCheck, inOutBounds);
}
/**
* Adjusts input bounds to avoid conflict with provided display bounds and list of tasks bounds
* for the display.
* Adjusts input bounds to avoid conflict with provided displayArea bounds and list of tasks
* bounds for the displayArea.
*
* Scans the bounds in directions to find a candidate location that does not conflict with the
* provided list of task bounds. If starting bounds are outside the display bounds or if no
* provided list of task bounds. If starting bounds are outside the displayArea bounds or if no
* suitable candidate bounds are found, the method returns the input bounds.
*
* @param displayBounds display bounds used to restrict the candidate bounds
* @param displayAreaBounds displayArea bounds used to restrict the candidate bounds
* @param taskBoundsToCheck list of task bounds to check for conflict
* @param inOutBounds the bounds used to input initial bounds and output result bounds
*/
@VisibleForTesting
void adjustBoundsToAvoidConflict(@NonNull Rect displayBounds,
void adjustBoundsToAvoidConflict(@NonNull Rect displayAreaBounds,
@NonNull List<Rect> taskBoundsToCheck,
@NonNull Rect inOutBounds) {
if (!displayBounds.contains(inOutBounds)) {
// The initial bounds are already out of display. The scanning algorithm below doesn't
// work so well with them.
if (!displayAreaBounds.contains(inOutBounds)) {
// The initial bounds are already out of displayArea. The scanning algorithm below
// doesn't work so well with them.
return;
}
@@ -897,7 +919,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
return;
}
calculateCandidateShiftDirections(displayBounds, inOutBounds);
calculateCandidateShiftDirections(displayAreaBounds, inOutBounds);
for (int direction : mTmpDirections) {
if (direction == Gravity.NO_GRAVITY) {
// We exhausted candidate directions, give up.
@@ -906,12 +928,12 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
mTmpBounds.set(inOutBounds);
while (boundsConflict(taskBoundsToCheck, mTmpBounds)
&& displayBounds.contains(mTmpBounds)) {
shiftBounds(direction, displayBounds, mTmpBounds);
&& displayAreaBounds.contains(mTmpBounds)) {
shiftBounds(direction, displayAreaBounds, mTmpBounds);
}
if (!boundsConflict(taskBoundsToCheck, mTmpBounds)
&& displayBounds.contains(mTmpBounds)) {
&& displayAreaBounds.contains(mTmpBounds)) {
// Found a candidate. Just use this.
inOutBounds.set(mTmpBounds);
if (DEBUG) appendLog("avoid-bounds-conflict=" + inOutBounds);

View File

@@ -473,6 +473,68 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
mDefaultDisplay.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea);
}
@Test
public void testRecalculateFreeformInitialBoundsWithOverrideDisplayArea() {
final TestDisplayContent freeformDisplay = createNewDisplayContent(
WINDOWING_MODE_FREEFORM);
final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(freeformDisplay,
mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
secondaryDisplayArea.setBounds(DISPLAY_BOUNDS.width() / 2, 0,
DISPLAY_BOUNDS.width(), DISPLAY_BOUNDS.height());
final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
launchRoot.mCreatedByOrganizer = true;
secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FREEFORM },
new int[] { ACTIVITY_TYPE_STANDARD });
final Rect secondaryDAStableBounds = new Rect();
secondaryDisplayArea.getStableRect(secondaryDAStableBounds);
// Specify the display and provide a layout so that it will be set to freeform bounds.
final ActivityOptions options = ActivityOptions.makeBasic()
.setLaunchDisplayId(freeformDisplay.getDisplayId());
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setGravity(Gravity.LEFT).build();
assertEquals(RESULT_CONTINUE,
new CalculateRequestBuilder().setOptions(options).setLayout(layout).calculate());
assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
assertTrue(secondaryDAStableBounds.contains(mResult.mBounds));
}
@Test
public void testRecalculateFreeformInitialBoundsWithOverrideDisplayArea_unresizableApp() {
mAtm.mSupportsNonResizableMultiWindow = true;
final TestDisplayContent freeformDisplay = createNewDisplayContent(
WINDOWING_MODE_FREEFORM);
final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(freeformDisplay,
mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
secondaryDisplayArea.setBounds(DISPLAY_BOUNDS.width() / 2, 0,
DISPLAY_BOUNDS.width(), DISPLAY_BOUNDS.height());
final Task launchRoot = createTaskStackOnTaskDisplayArea(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, secondaryDisplayArea);
launchRoot.mCreatedByOrganizer = true;
secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FREEFORM },
new int[] { ACTIVITY_TYPE_STANDARD });
final Rect secondaryDAStableBounds = new Rect();
secondaryDisplayArea.getStableRect(secondaryDAStableBounds);
// The bounds will get updated for unresizable with opposite orientation on freeform display
final Rect displayBounds = new Rect(freeformDisplay.getBounds());
mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
mActivity.info.screenOrientation = displayBounds.width() > displayBounds.height()
? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE;
final ActivityOptions options = ActivityOptions.makeBasic()
.setLaunchDisplayId(freeformDisplay.getDisplayId());
assertEquals(RESULT_CONTINUE,
new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(secondaryDisplayArea, mResult.mPreferredTaskDisplayArea);
assertTrue(secondaryDAStableBounds.contains(mResult.mBounds));
}
// =====================================
// Launch Windowing Mode Related Tests
// =====================================
@@ -1365,8 +1427,8 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
// This test case requires a relatively big app bounds to ensure the default size calculated
// by letterbox won't be too small to hold the minimum width/height.
configInsetsState(
freeformDisplay.getInsetsStateController().getRawInsetsState(),
DISPLAY_BOUNDS, new Rect(10, 10, 1910, 1070));
freeformDisplay.getInsetsStateController().getRawInsetsState(), freeformDisplay,
new Rect(10, 10, 1910, 1070));
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
@@ -1587,15 +1649,17 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
display.setBounds(DISPLAY_BOUNDS);
display.getConfiguration().densityDpi = DENSITY_DEFAULT;
display.getConfiguration().orientation = ORIENTATION_LANDSCAPE;
configInsetsState(display.getInsetsStateController().getRawInsetsState(),
DISPLAY_BOUNDS, DISPLAY_STABLE_BOUNDS);
configInsetsState(display.getInsetsStateController().getRawInsetsState(), display,
DISPLAY_STABLE_BOUNDS);
return display;
}
/**
* Creates insets sources so that we can get the expected stable frame.
*/
private static void configInsetsState(InsetsState state, Rect displayFrame, Rect stableFrame) {
private static void configInsetsState(InsetsState state, DisplayContent display,
Rect stableFrame) {
final Rect displayFrame = display.getBounds();
final int dl = displayFrame.left;
final int dt = displayFrame.top;
final int dr = displayFrame.right;
@@ -1618,6 +1682,8 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
if (sb < db) {
state.getSource(ITYPE_NAVIGATION_BAR).setFrame(dl, sb, dr, db);
}
// Recompute config and push to children.
display.onRequestedOverrideConfigurationChanged(display.getConfiguration());
}
private ActivityRecord createSourceActivity(TestDisplayContent display) {