diff options
| author | 2024-07-18 13:15:32 +0000 | |
|---|---|---|
| committer | 2024-07-18 13:15:32 +0000 | |
| commit | 8a2256314d3ddd7e91d99e714b547006cdf8f98b (patch) | |
| tree | 09e9d1ee2c6d245d9cd47176d733d186851a70e3 | |
| parent | afba13fe1b5e43f5197d8f593ed2fe558fdad172 (diff) | |
| parent | cd47f74012664c16bcb525c1a4d1291a30644956 (diff) | |
Merge "[2/n] Introduce dynamic bounds calculation to prevent letterboxing" into main
8 files changed, 560 insertions, 176 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt index 1bf125938e6f..da212e704b24 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt @@ -66,7 +66,7 @@ fun calculateInitialBounds( idealSize } } else { - maximumSizeMaintainingAspectRatio(taskInfo, idealSize, appAspectRatio) + maximizeSizeGivenAspectRatio(taskInfo, idealSize, appAspectRatio) } } ORIENTATION_PORTRAIT -> { @@ -85,13 +85,13 @@ fun calculateInitialBounds( } else { if (isFixedOrientationLandscape(topActivityInfo.screenOrientation)) { // Apply custom app width and calculate maximum size - maximumSizeMaintainingAspectRatio( + maximizeSizeGivenAspectRatio( taskInfo, Size(customPortraitWidthForLandscapeApp, idealSize.height), appAspectRatio ) } else { - maximumSizeMaintainingAspectRatio(taskInfo, idealSize, appAspectRatio) + maximizeSizeGivenAspectRatio(taskInfo, idealSize, appAspectRatio) } } } @@ -107,7 +107,7 @@ fun calculateInitialBounds( * Calculates the largest size that can fit in a given area while maintaining a specific aspect * ratio. */ -fun maximumSizeMaintainingAspectRatio( +fun maximizeSizeGivenAspectRatio( taskInfo: RunningTaskInfo, targetArea: Size, aspectRatio: Float diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 31f797a222a1..a91edaab1d6a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -671,7 +671,7 @@ class DesktopTasksController( } else { // if non-resizable then calculate max bounds according to aspect ratio val activityAspectRatio = calculateAspectRatio(taskInfo) - val newSize = maximumSizeMaintainingAspectRatio(taskInfo, + val newSize = maximizeSizeGivenAspectRatio(taskInfo, Size(stableBounds.width(), stableBounds.height()), activityAspectRatio) val newBounds = centerInArea( newSize, stableBounds, stableBounds.left, stableBounds.top) @@ -1079,7 +1079,6 @@ class DesktopTasksController( wct: WindowContainerTransaction, taskInfo: RunningTaskInfo ) { - val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return val tdaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(taskInfo.displayId)!! val tdaWindowingMode = tdaInfo.configuration.windowConfiguration.windowingMode val targetWindowingMode = @@ -1089,9 +1088,6 @@ class DesktopTasksController( } else { WINDOWING_MODE_FREEFORM } - if (Flags.enableWindowingDynamicInitialBounds()) { - wct.setBounds(taskInfo.token, calculateInitialBounds(displayLayout, taskInfo)) - } wct.setWindowingMode(taskInfo.token, targetWindowingMode) wct.reorder(taskInfo.token, true /* onTop */) if (useDesktopOverrideDensity()) { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index 6002c21ccb24..8421365e594d 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -580,138 +580,6 @@ class DesktopTasksControllerTest : ShellTestCase() { } @Test - @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) - fun moveToDesktop_landscapeDevice_resizable_undefinedOrientation_defaultLandscapeBounds() { - val task = setUpFullscreenTask() - setUpLandscapeDisplay() - - controller.moveToDesktop(task, transitionSource = UNKNOWN) - val wct = getLatestEnterDesktopWct() - assertThat(findBoundsChange(wct, task)).isEqualTo(DEFAULT_LANDSCAPE_BOUNDS) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) - fun moveToDesktop_landscapeDevice_resizable_landscapeOrientation_defaultLandscapeBounds() { - val task = setUpFullscreenTask(screenOrientation = SCREEN_ORIENTATION_LANDSCAPE) - setUpLandscapeDisplay() - - controller.moveToDesktop(task, transitionSource = UNKNOWN) - val wct = getLatestEnterDesktopWct() - assertThat(findBoundsChange(wct, task)).isEqualTo(DEFAULT_LANDSCAPE_BOUNDS) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) - fun moveToDesktop_landscapeDevice_resizable_portraitOrientation_resizablePortraitBounds() { - val task = - setUpFullscreenTask(screenOrientation = SCREEN_ORIENTATION_PORTRAIT, shouldLetterbox = true) - setUpLandscapeDisplay() - - controller.moveToDesktop(task, transitionSource = UNKNOWN) - val wct = getLatestEnterDesktopWct() - assertThat(findBoundsChange(wct, task)).isEqualTo(RESIZABLE_PORTRAIT_BOUNDS) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) - fun moveToDesktop_landscapeDevice_unResizable_landscapeOrientation_defaultLandscapeBounds() { - val task = - setUpFullscreenTask(isResizable = false, screenOrientation = SCREEN_ORIENTATION_LANDSCAPE) - setUpLandscapeDisplay() - - controller.moveToDesktop(task, transitionSource = UNKNOWN) - val wct = getLatestEnterDesktopWct() - assertThat(findBoundsChange(wct, task)).isEqualTo(DEFAULT_LANDSCAPE_BOUNDS) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) - fun moveToDesktop_landscapeDevice_unResizable_portraitOrientation_unResizablePortraitBounds() { - val task = - setUpFullscreenTask( - isResizable = false, - screenOrientation = SCREEN_ORIENTATION_PORTRAIT, - shouldLetterbox = true) - setUpLandscapeDisplay() - - controller.moveToDesktop(task, transitionSource = UNKNOWN) - val wct = getLatestEnterDesktopWct() - assertThat(findBoundsChange(wct, task)).isEqualTo(UNRESIZABLE_PORTRAIT_BOUNDS) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) - fun moveToDesktop_portraitDevice_resizable_undefinedOrientation_defaultPortraitBounds() { - val task = setUpFullscreenTask(deviceOrientation = ORIENTATION_PORTRAIT) - setUpPortraitDisplay() - - controller.moveToDesktop(task, transitionSource = UNKNOWN) - val wct = getLatestEnterDesktopWct() - assertThat(findBoundsChange(wct, task)).isEqualTo(DEFAULT_PORTRAIT_BOUNDS) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) - fun moveToDesktop_portraitDevice_resizable_portraitOrientation_defaultPortraitBounds() { - val task = - setUpFullscreenTask( - deviceOrientation = ORIENTATION_PORTRAIT, - screenOrientation = SCREEN_ORIENTATION_PORTRAIT) - setUpPortraitDisplay() - - controller.moveToDesktop(task, transitionSource = UNKNOWN) - val wct = getLatestEnterDesktopWct() - assertThat(findBoundsChange(wct, task)).isEqualTo(DEFAULT_PORTRAIT_BOUNDS) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) - fun moveToDesktop_portraitDevice_resizable_landscapeOrientation_resizableLandscapeBounds() { - val task = - setUpFullscreenTask( - deviceOrientation = ORIENTATION_PORTRAIT, - screenOrientation = SCREEN_ORIENTATION_LANDSCAPE, - shouldLetterbox = true) - setUpPortraitDisplay() - - controller.moveToDesktop(task, transitionSource = UNKNOWN) - val wct = getLatestEnterDesktopWct() - assertThat(findBoundsChange(wct, task)).isEqualTo(RESIZABLE_LANDSCAPE_BOUNDS) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) - fun moveToDesktop_portraitDevice_unResizable_portraitOrientation_defaultPortraitBounds() { - val task = - setUpFullscreenTask( - isResizable = false, - deviceOrientation = ORIENTATION_PORTRAIT, - screenOrientation = SCREEN_ORIENTATION_PORTRAIT) - setUpPortraitDisplay() - - controller.moveToDesktop(task, transitionSource = UNKNOWN) - val wct = getLatestEnterDesktopWct() - assertThat(findBoundsChange(wct, task)).isEqualTo(DEFAULT_PORTRAIT_BOUNDS) - } - - @Test - @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) - fun moveToDesktop_portraitDevice_unResizable_landscapeOrientation_unResizableLandscapeBounds() { - val task = - setUpFullscreenTask( - isResizable = false, - deviceOrientation = ORIENTATION_PORTRAIT, - screenOrientation = SCREEN_ORIENTATION_LANDSCAPE, - shouldLetterbox = true) - setUpPortraitDisplay() - - controller.moveToDesktop(task, transitionSource = UNKNOWN) - val wct = getLatestEnterDesktopWct() - assertThat(findBoundsChange(wct, task)).isEqualTo(UNRESIZABLE_LANDSCAPE_BOUNDS) - } - - @Test fun moveToDesktop_tdaFullscreen_windowingModeSetToFreeform() { val task = setUpFullscreenTask() val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!! diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java index d9f11b1635cc..05d4c821c161 100644 --- a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java +++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java @@ -226,6 +226,14 @@ class AppCompatAspectRatioOverrides { : getDefaultMinAspectRatio(); } + float getDefaultMinAspectRatioForUnresizableAppsFromConfig() { + return mAppCompatConfiguration.getDefaultMinAspectRatioForUnresizableApps(); + } + + boolean isSplitScreenAspectRatioForUnresizableAppsEnabled() { + return mAppCompatConfiguration.getIsSplitScreenAspectRatioForUnresizableAppsEnabled(); + } + private float getDisplaySizeMinAspectRatio() { final DisplayArea displayArea = mActivityRecord.getDisplayArea(); if (displayArea == null) { @@ -278,7 +286,7 @@ class AppCompatAspectRatioOverrides { return getSplitScreenAspectRatio(); } - private float getDefaultMinAspectRatio() { + float getDefaultMinAspectRatio() { if (mActivityRecord.getDisplayArea() == null || !mAppCompatConfiguration .getIsDisplayAspectRatioEnabledForFixedOrientationLetterbox()) { diff --git a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java index f9f5058415c6..3ecdff6b18a0 100644 --- a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java +++ b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java @@ -16,18 +16,33 @@ package com.android.server.wm; +import static android.content.pm.ActivityInfo.isFixedOrientationLandscape; +import static android.content.pm.ActivityInfo.isFixedOrientationPortrait; +import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import static android.content.res.Configuration.ORIENTATION_PORTRAIT; + +import static com.android.server.wm.AppCompatConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; +import static com.android.server.wm.AppCompatConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO; +import static com.android.server.wm.AppCompatUtils.computeAspectRatio; import static com.android.server.wm.LaunchParamsUtil.applyLayoutGravity; import static com.android.server.wm.LaunchParamsUtil.calculateLayoutBounds; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityOptions; +import android.app.AppCompatTaskInfo; +import android.app.TaskInfo; import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.graphics.Rect; import android.os.SystemProperties; import android.util.Size; import android.view.Gravity; +import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; +import com.android.window.flags.Flags; + import java.util.function.Consumer; /** @@ -38,6 +53,8 @@ public final class DesktopModeBoundsCalculator { public static final float DESKTOP_MODE_INITIAL_BOUNDS_SCALE = SystemProperties .getInt("persist.wm.debug.desktop_mode_initial_bounds_scale", 75) / 100f; + public static final int DESKTOP_MODE_LANDSCAPE_APP_PADDING = SystemProperties + .getInt("persist.wm.debug.desktop_mode_landscape_app_padding", 25); /** * Updates launch bounds for an activity with respect to its activity options, window layout, @@ -48,12 +65,8 @@ public final class DesktopModeBoundsCalculator { @NonNull Rect outBounds, @NonNull Consumer<String> logger) { // 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 TaskDisplayArea displayArea = task.getDisplayArea(); - final Rect screenBounds = displayArea.getBounds(); final Rect stableBounds = new Rect(); - displayArea.getStableRect(stableBounds); - final int desiredWidth = (int) (stableBounds.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - final int desiredHeight = (int) (stableBounds.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + task.getDisplayArea().getStableRect(stableBounds); if (options != null && options.getLaunchBounds() != null) { outBounds.set(options.getLaunchBounds()); @@ -63,37 +76,282 @@ public final class DesktopModeBoundsCalculator { final int horizontalGravity = layout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; if (layout.hasSpecifiedSize()) { calculateLayoutBounds(stableBounds, layout, outBounds, - new Size(desiredWidth, desiredHeight)); + calculateIdealSize(stableBounds, DESKTOP_MODE_INITIAL_BOUNDS_SCALE)); applyLayoutGravity(verticalGravity, horizontalGravity, outBounds, stableBounds); logger.accept("layout specifies sizes, inheriting size and applying gravity"); } else if (verticalGravity > 0 || horizontalGravity > 0) { - calculateAndCentreInitialBounds(outBounds, screenBounds); + outBounds.set(calculateInitialBounds(task, activity, stableBounds)); applyLayoutGravity(verticalGravity, horizontalGravity, outBounds, stableBounds); logger.accept("layout specifies gravity, applying desired bounds and gravity"); } } else { - calculateAndCentreInitialBounds(outBounds, screenBounds); + outBounds.set(calculateInitialBounds(task, activity, stableBounds)); logger.accept("layout not specified, applying desired bounds"); } } /** - * Calculates the initial height and width of a task in desktop mode and centers it within the - * window bounds. + * Calculates the initial bounds required for an application to fill a scale of the display + * bounds without any letterboxing. This is done by taking into account the applications + * fullscreen size, aspect ratio, orientation and resizability to calculate an area this is + * compatible with the applications previous configuration. + */ + private static @NonNull Rect calculateInitialBounds(@NonNull Task task, + @NonNull ActivityRecord activity, @NonNull Rect stableBounds + ) { + final TaskInfo taskInfo = task.getTaskInfo(); + // Display bounds not taking into account insets. + final TaskDisplayArea displayArea = task.getDisplayArea(); + final Rect screenBounds = displayArea.getBounds(); + final Size idealSize = calculateIdealSize(screenBounds, DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + if (!Flags.enableWindowingDynamicInitialBounds()) { + return centerInScreen(idealSize, screenBounds); + } + // TODO(b/353457301): Replace with app compat aspect ratio method when refactoring complete. + float appAspectRatio = calculateAspectRatio(task, activity); + final float tdaWidth = stableBounds.width(); + final float tdaHeight = stableBounds.height(); + final int activityOrientation = activity.getOverrideOrientation(); + final Size initialSize = switch (taskInfo.configuration.orientation) { + case ORIENTATION_LANDSCAPE -> { + // Device in landscape orientation. + if (appAspectRatio == 0) { + appAspectRatio = 1; + } + if (taskInfo.isResizeable) { + if (isFixedOrientationPortrait(activityOrientation)) { + // For portrait resizeable activities, respect apps fullscreen width but + // apply ideal size height. + yield new Size((int) ((tdaHeight / appAspectRatio) + 0.5f), + idealSize.getHeight()); + } + // For landscape resizeable activities, simply apply ideal size. + yield idealSize; + } + // If activity is unresizeable, regardless of orientation, calculate maximum size + // (within the ideal size) maintaining original aspect ratio. + yield maximizeSizeGivenAspectRatio( + activity.getOverrideOrientation(), idealSize, appAspectRatio); + } + case ORIENTATION_PORTRAIT -> { + // Device in portrait orientation. + final int customPortraitWidthForLandscapeApp = screenBounds.width() + - (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2); + if (taskInfo.isResizeable) { + if (isFixedOrientationLandscape(activityOrientation)) { + if (appAspectRatio == 0) { + appAspectRatio = tdaWidth / (tdaWidth - 1); + } + // For landscape resizeable activities, respect apps fullscreen height and + // apply custom app width. + yield new Size(customPortraitWidthForLandscapeApp, + (int) ((tdaWidth / appAspectRatio) + 0.5f)); + } + // For portrait resizeable activities, simply apply ideal size. + yield idealSize; + } + if (appAspectRatio == 0) { + appAspectRatio = 1; + } + if (isFixedOrientationLandscape(activityOrientation)) { + // For landscape unresizeable activities, apply custom app width to ideal size + // and calculate maximum size with this area while maintaining original aspect + // ratio. + yield maximizeSizeGivenAspectRatio(activityOrientation, + new Size(customPortraitWidthForLandscapeApp, idealSize.getHeight()), + appAspectRatio); + } + // For portrait unresizeable activities, calculate maximum size (within the ideal + // size) maintaining original aspect ratio. + yield maximizeSizeGivenAspectRatio(activityOrientation, idealSize, appAspectRatio); + } + default -> idealSize; + }; + return centerInScreen(initialSize, screenBounds); + } + + /** + * Calculates the largest size that can fit in a given area while maintaining a specific aspect + * ratio. + */ + private static @NonNull Size maximizeSizeGivenAspectRatio( + @ActivityInfo.ScreenOrientation int orientation, + @NonNull Size targetArea, + float aspectRatio + ) { + final int targetHeight = targetArea.getHeight(); + final int targetWidth = targetArea.getWidth(); + final int finalHeight; + final int finalWidth; + if (isFixedOrientationPortrait(orientation)) { + // Portrait activity. + // Calculate required width given ideal height and aspect ratio. + int tempWidth = (int) (targetHeight / aspectRatio); + if (tempWidth <= targetWidth) { + // If the calculated width does not exceed the ideal width, overall size is within + // ideal size and can be applied. + finalHeight = targetHeight; + finalWidth = tempWidth; + } else { + // Applying target height cause overall size to exceed ideal size when maintain + // aspect ratio. Instead apply ideal width and calculate required height to respect + // aspect ratio. + finalWidth = targetWidth; + finalHeight = (int) (finalWidth * aspectRatio); + } + } else { + // Landscape activity. + // Calculate required width given ideal height and aspect ratio. + int tempWidth = (int) (targetHeight * aspectRatio); + if (tempWidth <= targetWidth) { + // If the calculated width does not exceed the ideal width, overall size is within + // ideal size and can be applied. + finalHeight = targetHeight; + finalWidth = tempWidth; + } else { + // Applying target height cause overall size to exceed ideal size when maintain + // aspect ratio. Instead apply ideal width and calculate required height to respect + // aspect ratio. + finalWidth = targetWidth; + finalHeight = (int) (finalWidth / aspectRatio); + } + } + return new Size(finalWidth, finalHeight); + } + + /** + * Calculates the aspect ratio of an activity from its fullscreen bounds. + */ + @VisibleForTesting + static float calculateAspectRatio(@NonNull Task task, @NonNull ActivityRecord activity) { + final TaskInfo taskInfo = task.getTaskInfo(); + final float fullscreenWidth = task.getDisplayArea().getBounds().width(); + final float fullscreenHeight = task.getDisplayArea().getBounds().height(); + final float maxAspectRatio = activity.getMaxAspectRatio(); + final float minAspectRatio = activity.getMinAspectRatio(); + float desiredAspectRatio = 0; + if (taskInfo.isRunning) { + final AppCompatTaskInfo appCompatTaskInfo = taskInfo.appCompatTaskInfo; + if (appCompatTaskInfo.topActivityBoundsLetterboxed) { + desiredAspectRatio = (float) Math.max( + appCompatTaskInfo.topActivityLetterboxWidth, + appCompatTaskInfo.topActivityLetterboxHeight) + / Math.min(appCompatTaskInfo.topActivityLetterboxWidth, + appCompatTaskInfo.topActivityLetterboxHeight); + } else { + desiredAspectRatio = Math.max(fullscreenHeight, fullscreenWidth) + / Math.min(fullscreenHeight, fullscreenWidth); + } + } else { + final float letterboxAspectRatioOverride = + getFixedOrientationLetterboxAspectRatio(activity, task); + if (!task.mDisplayContent.getIgnoreOrientationRequest()) { + desiredAspectRatio = DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW; + } else if (letterboxAspectRatioOverride + > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) { + desiredAspectRatio = letterboxAspectRatioOverride; + } + } + // If the activity matches display orientation, the display aspect ratio should be used + if (activityMatchesDisplayOrientation( + taskInfo.configuration.orientation, + activity.getOverrideOrientation())) { + desiredAspectRatio = Math.max(fullscreenWidth, fullscreenHeight) + / Math.min(fullscreenWidth, fullscreenHeight); + } + if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) { + desiredAspectRatio = maxAspectRatio; + } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) { + desiredAspectRatio = minAspectRatio; + } + return desiredAspectRatio; + } + + private static boolean activityMatchesDisplayOrientation( + @Configuration.Orientation int deviceOrientation, + @ActivityInfo.ScreenOrientation int activityOrientation) { + if (deviceOrientation == ORIENTATION_PORTRAIT) { + return isFixedOrientationPortrait(activityOrientation); + } + return isFixedOrientationLandscape(activityOrientation); + } + + /** + * Calculates the desired initial bounds for applications in desktop windowing. This is done as + * a scale of the screen bounds. + */ + private static @NonNull Size calculateIdealSize(@NonNull Rect screenBounds, float scale) { + final int width = (int) (screenBounds.width() * scale); + final int height = (int) (screenBounds.height() * scale); + return new Size(width, height); + } + + /** + * Adjusts bounds to be positioned in the middle of the screen. */ - private static void calculateAndCentreInitialBounds(@NonNull Rect outBounds, + private static @NonNull Rect centerInScreen(@NonNull Size desiredSize, @NonNull Rect screenBounds) { - // TODO(b/319819547): Account for app constraints so apps do not become letterboxed - // The desired dimensions that a fully resizable window should take when initially entering - // desktop mode. Calculated as a percentage of the available display area as defined by the - // DESKTOP_MODE_INITIAL_BOUNDS_SCALE. - final int desiredWidth = (int) (screenBounds.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - final int desiredHeight = (int) (screenBounds.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); - outBounds.right = desiredWidth; - outBounds.bottom = desiredHeight; - outBounds.offset(screenBounds.centerX() - outBounds.centerX(), - screenBounds.centerY() - outBounds.centerY()); + // TODO(b/325240051): Position apps with bottom heavy offset + final int heightOffset = (screenBounds.height() - desiredSize.getHeight()) / 2; + final int widthOffset = (screenBounds.width() - desiredSize.getWidth()) / 2; + final Rect resultBounds = new Rect(0, 0, + desiredSize.getWidth(), desiredSize.getHeight()); + resultBounds.offset(screenBounds.left + widthOffset, screenBounds.top + heightOffset); + return resultBounds; + } + + private static float getFixedOrientationLetterboxAspectRatio(@NonNull ActivityRecord activity, + @NonNull Task task) { + return activity.shouldCreateCompatDisplayInsets() + ? getDefaultMinAspectRatioForUnresizableApps(activity, task) + : activity.mAppCompatController.getAppCompatAspectRatioOverrides() + .getDefaultMinAspectRatio(); + } + + private static float getDefaultMinAspectRatioForUnresizableApps( + @NonNull ActivityRecord activity, + @NonNull Task task) { + final AppCompatAspectRatioOverrides appCompatAspectRatioOverrides = + activity.mAppCompatController.getAppCompatAspectRatioOverrides(); + if (appCompatAspectRatioOverrides.isSplitScreenAspectRatioForUnresizableAppsEnabled()) { + // Default letterbox aspect ratio for unresizable apps. + return getSplitScreenAspectRatio(activity, task); + } + + if (appCompatAspectRatioOverrides.getDefaultMinAspectRatioForUnresizableAppsFromConfig() + > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) { + return appCompatAspectRatioOverrides + .getDefaultMinAspectRatioForUnresizableAppsFromConfig(); + } + + return appCompatAspectRatioOverrides.getDefaultMinAspectRatio(); + } + + /** + * Calculates the aspect ratio of the available display area when an app enters split-screen on + * a given device, taking into account any dividers and insets. + */ + private static float getSplitScreenAspectRatio(@NonNull ActivityRecord activity, + @NonNull Task task) { + final int dividerWindowWidth = + activity.mWmService.mContext.getResources().getDimensionPixelSize( + R.dimen.docked_stack_divider_thickness); + final int dividerInsets = + activity.mWmService.mContext.getResources().getDimensionPixelSize( + R.dimen.docked_stack_divider_insets); + final int dividerSize = dividerWindowWidth - dividerInsets * 2; + final Rect bounds = new Rect(0, 0, + task.mDisplayContent.getDisplayInfo().appWidth, + task.mDisplayContent.getDisplayInfo().appHeight); + if (bounds.width() >= bounds.height()) { + bounds.inset(/* dx */ dividerSize / 2, /* dy */ 0); + bounds.right = bounds.centerX(); + } else { + bounds.inset(/* dx */ 0, /* dy */ dividerSize / 2); + bounds.bottom = bounds.centerY(); + } + return computeAspectRatio(bounds); } } diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java index aacd3c65154f..548addbef39d 100644 --- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java @@ -25,7 +25,6 @@ import android.annotation.Nullable; import android.app.ActivityOptions; import android.content.Context; import android.content.pm.ActivityInfo; -import android.os.SystemProperties; import android.util.Slog; import com.android.server.wm.LaunchParamsController.LaunchParamsModifier; @@ -38,19 +37,9 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier { TAG_WITH_CLASS_NAME ? "DesktopModeLaunchParamsModifier" : TAG_ATM; private static final boolean DEBUG = false; - public static final float DESKTOP_MODE_INITIAL_BOUNDS_SCALE = - SystemProperties - .getInt("persist.wm.debug.desktop_mode_initial_bounds_scale", 75) / 100f; - - /** - * Flag to indicate whether to restrict desktop mode to supported devices. - */ - private static final boolean ENFORCE_DEVICE_RESTRICTIONS = SystemProperties.getBoolean( - "persist.wm.debug.desktop_mode_enforce_device_restrictions", true); - private StringBuilder mLogBuilder; - private final Context mContext; + @NonNull private final Context mContext; DesktopModeLaunchParamsModifier(@NonNull Context context) { mContext = context; diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java index 23a88a1774f4..b687042edfc3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java @@ -21,9 +21,19 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; +import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; +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.util.DisplayMetrics.DENSITY_DEFAULT; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.android.server.wm.DesktopModeLaunchParamsModifier.DESKTOP_MODE_INITIAL_BOUNDS_SCALE; +import static com.android.server.wm.DesktopModeBoundsCalculator.DESKTOP_MODE_INITIAL_BOUNDS_SCALE; +import static com.android.server.wm.DesktopModeBoundsCalculator.DESKTOP_MODE_LANDSCAPE_APP_PADDING; +import static com.android.server.wm.DesktopModeBoundsCalculator.calculateAspectRatio; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP; @@ -59,6 +69,10 @@ import org.junit.runner.RunWith; @RunWith(WindowTestRunner.class) public class DesktopModeLaunchParamsModifierTests extends LaunchParamsModifierTestsBase<DesktopModeLaunchParamsModifier> { + private static final Rect LANDSCAPE_DISPLAY_BOUNDS = new Rect(0, 0, 2560, 1600); + private static final Rect PORTRAIT_DISPLAY_BOUNDS = new Rect(0, 0, 1600, 2560); + private static final float LETTERBOX_ASPECT_RATIO = 1.3f; + @Before public void setUp() throws Exception { mActivity = new ActivityBuilder(mAtm).build(); @@ -158,6 +172,7 @@ public class DesktopModeLaunchParamsModifierTests extends @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) + @DisableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) public void testUsesDesiredBoundsIfEmptyLayoutAndActivityOptionsBounds() { setupDesktopModeLaunchParamsModifier(); @@ -169,6 +184,209 @@ public class DesktopModeLaunchParamsModifierTests extends (int) (DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); final int desiredHeight = (int) (DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, + Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS}) + public void testDefaultLandscapeBounds_landscapeDevice_resizable_undefinedOrientation() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, SCREEN_ORIENTATION_UNSPECIFIED, true); + + final int desiredWidth = + (int) (LANDSCAPE_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, + Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS}) + public void testDefaultLandscapeBounds_landscapeDevice_resizable_landscapeOrientation() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, true); + + final int desiredWidth = + (int) (LANDSCAPE_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testResizablePortraitBounds_landscapeDevice_resizable_portraitOrientation() { + setupDesktopModeLaunchParamsModifier(); + doReturn(LETTERBOX_ASPECT_RATIO).when(() + -> calculateAspectRatio(any(), any())); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, true); + + final int desiredWidth = + (int) ((LANDSCAPE_DISPLAY_BOUNDS.height() / LETTERBOX_ASPECT_RATIO) + 0.5f); + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, + Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS}) + public void testDefaultLandscapeBounds_landscapeDevice_unResizable_landscapeOrientation() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, false); + + final int desiredWidth = + (int) (LANDSCAPE_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUnResizablePortraitBounds_landscapeDevice_unResizable_portraitOrientation() { + setupDesktopModeLaunchParamsModifier(); + doReturn(LETTERBOX_ASPECT_RATIO).when(() + -> calculateAspectRatio(any(), any())); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_LANDSCAPE, + LANDSCAPE_DISPLAY_BOUNDS); + final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, false); + + final int desiredHeight = + (int) (LANDSCAPE_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredWidth = (int) (desiredHeight / LETTERBOX_ASPECT_RATIO); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, + Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS}) + public void testDefaultPortraitBounds_portraitDevice_resizable_undefinedOrientation() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, SCREEN_ORIENTATION_UNSPECIFIED, true); + + final int desiredWidth = + (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = + (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, + Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS}) + public void testDefaultPortraitBounds_portraitDevice_resizable_portraitOrientation() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, true); + + final int desiredWidth = + (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = + (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testResizableLandscapeBounds_portraitDevice_resizable_landscapeOrientation() { + setupDesktopModeLaunchParamsModifier(); + doReturn(LETTERBOX_ASPECT_RATIO).when(() + -> calculateAspectRatio(any(), any())); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, true); + + final int desiredWidth = PORTRAIT_DISPLAY_BOUNDS.width() + - (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2); + final int desiredHeight = (int) + ((PORTRAIT_DISPLAY_BOUNDS.width() / LETTERBOX_ASPECT_RATIO) + 0.5f); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, + Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS}) + public void testDefaultPortraitBounds_portraitDevice_unResizable_portraitOrientation() { + setupDesktopModeLaunchParamsModifier(); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, SCREEN_ORIENTATION_PORTRAIT, false); + + final int desiredWidth = + (int) (PORTRAIT_DISPLAY_BOUNDS.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + final int desiredHeight = + (int) (PORTRAIT_DISPLAY_BOUNDS.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); + assertEquals(desiredWidth, mResult.mBounds.width()); + assertEquals(desiredHeight, mResult.mBounds.height()); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_WINDOWING_DYNAMIC_INITIAL_BOUNDS) + public void testUnResizableLandscapeBounds_portraitDevice_unResizable_landscapeOrientation() { + setupDesktopModeLaunchParamsModifier(); + doReturn(LETTERBOX_ASPECT_RATIO).when(() + -> calculateAspectRatio(any(), any())); + + final TestDisplayContent display = createDisplayContent(ORIENTATION_PORTRAIT, + PORTRAIT_DISPLAY_BOUNDS); + final Task task = createTask(display, SCREEN_ORIENTATION_LANDSCAPE, false); + + final int desiredWidth = PORTRAIT_DISPLAY_BOUNDS.width() + - (DESKTOP_MODE_LANDSCAPE_APP_PADDING * 2); + final int desiredHeight = (int) (desiredWidth / LETTERBOX_ASPECT_RATIO); + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(task).calculate()); assertEquals(desiredWidth, mResult.mBounds.width()); assertEquals(desiredHeight, mResult.mBounds.height()); @@ -192,6 +410,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBounds_CenterToDisplay() { setupDesktopModeLaunchParamsModifier(); @@ -207,6 +426,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBounds_LeftGravity() { setupDesktopModeLaunchParamsModifier(); @@ -222,6 +442,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBounds_TopGravity() { setupDesktopModeLaunchParamsModifier(); @@ -237,6 +458,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBounds_TopLeftGravity() { setupDesktopModeLaunchParamsModifier(); @@ -252,6 +474,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBounds_RightGravity() { setupDesktopModeLaunchParamsModifier(); @@ -267,6 +490,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBounds_BottomGravity() { setupDesktopModeLaunchParamsModifier(); @@ -282,6 +506,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBounds_RightBottomGravity() { setupDesktopModeLaunchParamsModifier(); @@ -297,6 +522,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutFractionBounds() { setupDesktopModeLaunchParamsModifier(); @@ -312,6 +538,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_LeftGravity() { setupDesktopModeLaunchParamsModifier(); @@ -327,6 +554,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_TopGravity() { setupDesktopModeLaunchParamsModifier(); @@ -342,6 +570,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_TopLeftGravity() { setupDesktopModeLaunchParamsModifier(); @@ -359,6 +588,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_RightGravity() { setupDesktopModeLaunchParamsModifier(); @@ -374,6 +604,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_BottomGravity() { setupDesktopModeLaunchParamsModifier(); @@ -389,6 +620,7 @@ public class DesktopModeLaunchParamsModifierTests extends } @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) public void testNonEmptyLayoutBoundsRespectsGravityWithEmptySize_BottomRightGravity() { setupDesktopModeLaunchParamsModifier(); @@ -422,6 +654,38 @@ public class DesktopModeLaunchParamsModifierTests extends assertEquals(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode); } + private Task createTask(DisplayContent display, int orientation, Boolean isResizeable) { + final int resizeMode = isResizeable ? RESIZE_MODE_RESIZEABLE + : RESIZE_MODE_UNRESIZEABLE; + final Task task = new TaskBuilder(mSupervisor).setActivityType( + ACTIVITY_TYPE_STANDARD).setDisplay(display).build(); + task.setResizeMode(resizeMode); + mActivity = new ActivityBuilder(task.mAtmService) + .setTask(task) + .setScreenOrientation(orientation) + .setOnTop(true).build(); + + mActivity.onDisplayChanged(display); + mActivity.setOccludesParent(true); + mActivity.setVisible(true); + mActivity.setVisibleRequested(true); + mActivity.mDisplayContent.setIgnoreOrientationRequest(/* ignoreOrientationRequest */ true); + + return task; + } + + private TestDisplayContent createDisplayContent(int orientation, Rect displayBounds) { + final TestDisplayContent display = new TestDisplayContent + .Builder(mAtm, displayBounds.width(), displayBounds.height()) + .setPosition(DisplayContent.POSITION_TOP).build(); + display.setBounds(displayBounds); + display.getConfiguration().densityDpi = DENSITY_DEFAULT; + display.getConfiguration().orientation = ORIENTATION_LANDSCAPE; + display.getDefaultTaskDisplayArea().setWindowingMode(orientation); + + return display; + } + private void setupDesktopModeLaunchParamsModifier() { setupDesktopModeLaunchParamsModifier(/*isDesktopModeSupported=*/ true, /*enforceDeviceRestrictions=*/ true); diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index a816aa9b7598..d5d284783978 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -203,6 +203,7 @@ public class SystemServicesTestRule implements TestRule { .mockStatic(LockGuard.class, mockStubOnly) .mockStatic(Watchdog.class, mockStubOnly) .spyStatic(DesktopModeHelper.class) + .spyStatic(DesktopModeBoundsCalculator.class) .strictness(Strictness.LENIENT) .startMocking(); |