diff options
13 files changed, 616 insertions, 134 deletions
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 22f42980d858..50761bfadbaf 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -5204,6 +5204,15 @@ the format [System DeviceState]:[WM Jetpack Posture], for example: "0:1". --> <string-array name="config_device_state_postures" translatable="false" /> + <!-- Which Surface rotations are considered as tabletop posture (horizontal hinge) when the + device is half-folded. Other half-folded postures will be assumed to be book (vertical + hinge) mode. Units: degrees; valid values: 0, 90, 180, 270. --> + <integer-array name="config_deviceTabletopRotations" /> + + <!-- This flag indicates that a display with fold-state FLAT should always be considered as + having a separating hinge. --> + <bool name="config_isDisplayHingeAlwaysSeparating">false</bool> + <!-- Aspect ratio of letterboxing for fixed orientation. Values <= 1.0 will be ignored. Note: Activity min/max aspect ratio restrictions will still be respected. Therefore this override can control the maximum screen area that can be occupied by @@ -5252,14 +5261,26 @@ <!-- Horizontal position of a center of the letterboxed app window. 0 corresponds to the left side of the screen and 1 to the right side. If given value < 0 - or > 1, it is ignored and central position is used (0.5). --> + or > 1 it is ignored and for non-book mode central position is used (0.5); for book mode + left is used (0.0). --> <item name="config_letterboxHorizontalPositionMultiplier" format="float" type="dimen">0.5</item> <!-- Vertical position of a center of the letterboxed app window. 0 corresponds to the upper side of the screen and 1 to the lower side. If given value < 0 - or > 1, it is ignored and central position is used (0.5). --> + or > 1 it is ignored and for non-tabletop mode central position is used (0.5); for + tabletop mode top (0.0) is used. --> <item name="config_letterboxVerticalPositionMultiplier" format="float" type="dimen">0.0</item> + <!-- Horizontal position of a center of the letterboxed app window when in book mode. + 0 corresponds to the left side of the screen and 1 to the right side. If given value < 0 + or > 1, it is ignored and left position is used (0.0). --> + <item name="config_letterboxBookModePositionMultiplier" format="float" type="dimen">0.0</item> + + <!-- Vertical position of a center of the letterboxed app window when in tabletop mode. + 0 corresponds to the upper side of the screen and 1 to the lower side. If given value < 0 + or > 1, it is ignored and top position is used (0.0). --> + <item name="config_letterboxTabletopModePositionMultiplier" format="float" type="dimen">0.0</item> + <!-- Whether horizontal reachability repositioning is allowed for letterboxed fullscreen apps. --> <bool name="config_letterboxIsHorizontalReachabilityEnabled">false</bool> @@ -5287,6 +5308,26 @@ If given value is outside of this range, the option 1 (center) is assummed. --> <integer name="config_letterboxDefaultPositionForVerticalReachability">1</integer> + <!-- Default horizontal position of the letterboxed app window when reachability is + enabled and an app is fullscreen in landscape device orientation and in book mode. When + reachability is enabled, the position can change between left, center and right. This config + defines the default one: + - Option 0 - Left. + - Option 1 - Center. + - Option 2 - Right. + If given value is outside of this range, the option 0 (left) is assummed. --> + <integer name="config_letterboxDefaultPositionForBookModeReachability">0</integer> + + <!-- Default vertical position of the letterboxed app window when reachability is + enabled and an app is fullscreen in portrait device orientation and in tabletop mode. When + reachability is enabled, the position can change between top, center and bottom. This config + defines the default one: + - Option 0 - Top. + - Option 1 - Center. + - Option 2 - Bottom. + If given value is outside of this range, the option 0 (top) is assummed. --> + <integer name="config_letterboxDefaultPositionForTabletopModeReachability">0</integer> + <!-- Whether displaying letterbox education is enabled for letterboxed fullscreen apps. --> <bool name="config_letterboxIsEducationEnabled">false</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b0f6ae6085e3..4fba845e34c2 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4434,6 +4434,8 @@ <java-symbol type="array" name="config_keep_warming_services" /> <java-symbol type="string" name="config_display_features" /> <java-symbol type="array" name="config_device_state_postures" /> + <java-symbol type="array" name="config_deviceTabletopRotations" /> + <java-symbol type="bool" name="config_isDisplayHingeAlwaysSeparating" /> <java-symbol type="dimen" name="controls_thumbnail_image_max_height" /> <java-symbol type="dimen" name="controls_thumbnail_image_max_width" /> @@ -4446,10 +4448,14 @@ <java-symbol type="color" name="config_letterboxBackgroundColor" /> <java-symbol type="dimen" name="config_letterboxHorizontalPositionMultiplier" /> <java-symbol type="dimen" name="config_letterboxVerticalPositionMultiplier" /> + <java-symbol type="dimen" name="config_letterboxBookModePositionMultiplier" /> + <java-symbol type="dimen" name="config_letterboxTabletopModePositionMultiplier" /> <java-symbol type="bool" name="config_letterboxIsHorizontalReachabilityEnabled" /> <java-symbol type="bool" name="config_letterboxIsVerticalReachabilityEnabled" /> <java-symbol type="integer" name="config_letterboxDefaultPositionForHorizontalReachability" /> <java-symbol type="integer" name="config_letterboxDefaultPositionForVerticalReachability" /> + <java-symbol type="integer" name="config_letterboxDefaultPositionForBookModeReachability" /> + <java-symbol type="integer" name="config_letterboxDefaultPositionForTabletopModeReachability" /> <java-symbol type="bool" name="config_letterboxIsEducationEnabled" /> <java-symbol type="dimen" name="config_letterboxDefaultMinAspectRatioForUnresizableApps" /> <java-symbol type="bool" name="config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled" /> diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 86c8097ee674..49704d971b8d 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -1525,6 +1525,12 @@ "group": "WM_DEBUG_FOCUS_LIGHT", "at": "com\/android\/server\/wm\/DisplayContent.java" }, + "-637815408": { + "message": "Invalid surface rotation angle in config_deviceTabletopRotations: %d", + "level": "ERROR", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" + }, "-636553602": { "message": "commitVisibility: %s: visible=%b visibleRequested=%b, isInTransition=%b, runningAnimation=%b, caller=%s", "level": "VERBOSE", @@ -3193,6 +3199,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/TaskFragment.java" }, + "939638078": { + "message": "config_deviceTabletopRotations is not defined. Half-fold letterboxing will work inconsistently.", + "level": "WARN", + "group": "WM_DEBUG_ORIENTATION", + "at": "com\/android\/server\/wm\/DisplayRotation.java" + }, "948208142": { "message": "Setting Activity.mLauncherTaskBehind to true. Activity=%s", "level": "DEBUG", diff --git a/proto/src/windowmanager.proto b/proto/src/windowmanager.proto index f26404c66623..da4dfa98401e 100644 --- a/proto/src/windowmanager.proto +++ b/proto/src/windowmanager.proto @@ -68,4 +68,8 @@ message LetterboxProto { LetterboxHorizontalReachability letterbox_position_for_horizontal_reachability = 1; // Represents the current vertical position for the letterboxed activity LetterboxVerticalReachability letterbox_position_for_vertical_reachability = 2; + // Represents the current horizontal position for the letterboxed activity in book mode + LetterboxHorizontalReachability letterbox_position_for_book_mode_reachability = 3; + // Represents the current vertical position for the letterboxed activity in tabletop mode + LetterboxVerticalReachability letterbox_position_for_tabletop_mode_reachability = 4; }
\ No newline at end of file diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 418e1edca05b..57eeb9a0a905 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -8149,7 +8149,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** - * Adjusts position of resolved bounds if they doesn't fill the parent using gravity + * Adjusts position of resolved bounds if they don't fill the parent using gravity * requested in the config or via an ADB command. For more context see {@link * LetterboxUiController#getHorizontalPositionMultiplier(Configuration)} and * {@link LetterboxUiController#getVerticalPositionMultiplier(Configuration)} @@ -8168,9 +8168,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A int offsetX = 0; if (parentBounds.width() != screenResolvedBounds.width()) { if (screenResolvedBounds.width() <= parentAppBounds.width()) { - float positionMultiplier = - mLetterboxUiController.getHorizontalPositionMultiplier( - newParentConfiguration); + float positionMultiplier = mLetterboxUiController.getHorizontalPositionMultiplier( + newParentConfiguration); offsetX = (int) Math.ceil((parentAppBounds.width() - screenResolvedBounds.width()) * positionMultiplier); } @@ -8180,9 +8179,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A int offsetY = 0; if (parentBounds.height() != screenResolvedBounds.height()) { if (screenResolvedBounds.height() <= parentAppBounds.height()) { - float positionMultiplier = - mLetterboxUiController.getVerticalPositionMultiplier( - newParentConfiguration); + float positionMultiplier = mLetterboxUiController.getVerticalPositionMultiplier( + newParentConfiguration); offsetY = (int) Math.ceil((parentAppBounds.height() - screenResolvedBounds.height()) * positionMultiplier); } diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 185e06eecabb..fc208e3e2605 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.util.RotationUtils.deltaRotation; @@ -55,6 +56,7 @@ import android.os.Handler; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; +import android.util.ArraySet; import android.util.Slog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; @@ -75,6 +77,7 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayDeque; +import java.util.Set; /** * Defines the mapping between orientation and rotation of a display. @@ -1521,6 +1524,15 @@ public class DisplayRotation { proto.end(token); } + boolean isDeviceInPosture(DeviceStateController.FoldState state, boolean isTabletop) { + if (mFoldController == null) return false; + return mFoldController.isDeviceInPosture(state, isTabletop); + } + + boolean isDisplaySeparatingHinge() { + return mFoldController != null && mFoldController.isSeparatingHinge(); + } + /** * Called by the DeviceStateManager callback when the device state changes. */ @@ -1538,6 +1550,63 @@ public class DisplayRotation { private DeviceStateController.FoldState mFoldState = DeviceStateController.FoldState.UNKNOWN; private boolean mInHalfFoldTransition = false; + private final boolean mIsDisplayAlwaysSeparatingHinge; + private final Set<Integer> mTabletopRotations; + + FoldController() { + mTabletopRotations = new ArraySet<>(); + int[] tabletop_rotations = mContext.getResources().getIntArray( + R.array.config_deviceTabletopRotations); + if (tabletop_rotations != null) { + for (int angle : tabletop_rotations) { + switch (angle) { + case 0: + mTabletopRotations.add(Surface.ROTATION_0); + break; + case 90: + mTabletopRotations.add(Surface.ROTATION_90); + break; + case 180: + mTabletopRotations.add(Surface.ROTATION_180); + break; + case 270: + mTabletopRotations.add(Surface.ROTATION_270); + break; + default: + ProtoLog.e(WM_DEBUG_ORIENTATION, + "Invalid surface rotation angle in " + + "config_deviceTabletopRotations: %d", + angle); + } + } + } else { + ProtoLog.w(WM_DEBUG_ORIENTATION, + "config_deviceTabletopRotations is not defined. Half-fold " + + "letterboxing will work inconsistently."); + } + mIsDisplayAlwaysSeparatingHinge = mContext.getResources().getBoolean( + R.bool.config_isDisplayHingeAlwaysSeparating); + } + + boolean isDeviceInPosture(DeviceStateController.FoldState state, boolean isTabletop) { + if (state != mFoldState) { + return false; + } + if (mFoldState == DeviceStateController.FoldState.HALF_FOLDED) { + return !(isTabletop ^ mTabletopRotations.contains(mRotation)); + } + return true; + } + + DeviceStateController.FoldState getFoldState() { + return mFoldState; + } + + boolean isSeparatingHinge() { + return mFoldState == DeviceStateController.FoldState.HALF_FOLDED + || (mFoldState == DeviceStateController.FoldState.OPEN + && mIsDisplayAlwaysSeparatingHinge); + } boolean overrideFrozenRotation() { return mFoldState == DeviceStateController.FoldState.HALF_FOLDED; @@ -1586,6 +1655,15 @@ public class DisplayRotation { mService.updateRotation(false /* alwaysSendConfiguration */, false /* forceRelayout */); } + // Alert the activity of possible new bounds. + final Task topFullscreenTask = + mDisplayContent.getTask(t -> t.getWindowingMode() == WINDOWING_MODE_FULLSCREEN); + if (topFullscreenTask != null) { + final ActivityRecord top = topFullscreenTask.topRunningActivity(); + if (top != null) { + top.recomputeConfiguration(); + } + } } } diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java index 127a7bf1c9a5..3eca364ff5fc 100644 --- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java +++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java @@ -16,12 +16,16 @@ package com.android.server.wm; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.graphics.Color; import android.provider.DeviceConfig; +import android.util.Slog; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -33,6 +37,8 @@ import java.util.function.Function; /** Reads letterbox configs from resources and controls their overrides at runtime. */ final class LetterboxConfiguration { + private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxConfiguration" : TAG_ATM; + /** * Override of aspect ratio for fixed orientation letterboxing that is set via ADB with * set-fixed-orientation-letterbox-aspect-ratio or via {@link @@ -144,6 +150,14 @@ final class LetterboxConfiguration { // side of the screen and 1.0 to the bottom side. private float mLetterboxVerticalPositionMultiplier; + // Horizontal position of a center of the letterboxed app window when the device is half-folded. + // 0 corresponds to the left side of the screen and 1.0 to the right side. + private float mLetterboxBookModePositionMultiplier; + + // Vertical position of a center of the letterboxed app window when the device is half-folded. + // 0 corresponds to the top side of the screen and 1.0 to the bottom side. + private float mLetterboxTabletopModePositionMultiplier; + // Default horizontal position the letterboxed app window when horizontal reachability is // enabled and an app is fullscreen in landscape device orientation. // It is used as a starting point for mLetterboxPositionForHorizontalReachability. @@ -179,8 +193,15 @@ final class LetterboxConfiguration { LetterboxConfiguration(Context systemUiContext) { this(systemUiContext, new LetterboxConfigurationPersister(systemUiContext, - () -> readLetterboxHorizontalReachabilityPositionFromConfig(systemUiContext), - () -> readLetterboxVerticalReachabilityPositionFromConfig(systemUiContext))); + () -> readLetterboxHorizontalReachabilityPositionFromConfig(systemUiContext, + /* forBookMode */ false), + () -> readLetterboxVerticalReachabilityPositionFromConfig(systemUiContext, + /* forTabletopMode */ false), + () -> readLetterboxHorizontalReachabilityPositionFromConfig(systemUiContext, + /* forBookMode */ true), + () -> readLetterboxVerticalReachabilityPositionFromConfig(systemUiContext, + /* forTabletopMode */ true) + )); } @VisibleForTesting @@ -200,14 +221,18 @@ final class LetterboxConfiguration { R.dimen.config_letterboxHorizontalPositionMultiplier); mLetterboxVerticalPositionMultiplier = mContext.getResources().getFloat( R.dimen.config_letterboxVerticalPositionMultiplier); + mLetterboxBookModePositionMultiplier = mContext.getResources().getFloat( + R.dimen.config_letterboxBookModePositionMultiplier); + mLetterboxTabletopModePositionMultiplier = mContext.getResources().getFloat( + R.dimen.config_letterboxTabletopModePositionMultiplier); mIsHorizontalReachabilityEnabled = mContext.getResources().getBoolean( R.bool.config_letterboxIsHorizontalReachabilityEnabled); mIsVerticalReachabilityEnabled = mContext.getResources().getBoolean( R.bool.config_letterboxIsVerticalReachabilityEnabled); mDefaultPositionForHorizontalReachability = - readLetterboxHorizontalReachabilityPositionFromConfig(mContext); + readLetterboxHorizontalReachabilityPositionFromConfig(mContext, false); mDefaultPositionForVerticalReachability = - readLetterboxVerticalReachabilityPositionFromConfig(mContext); + readLetterboxVerticalReachabilityPositionFromConfig(mContext, false); mIsEducationEnabled = mContext.getResources().getBoolean( R.bool.config_letterboxIsEducationEnabled); setDefaultMinAspectRatioForUnresizableApps(mContext.getResources().getFloat( @@ -460,11 +485,30 @@ final class LetterboxConfiguration { * or via an ADB command. 0 corresponds to the left side of the screen and 1 to the * right side. */ - float getLetterboxHorizontalPositionMultiplier() { - return (mLetterboxHorizontalPositionMultiplier < 0.0f - || mLetterboxHorizontalPositionMultiplier > 1.0f) - // Default to central position if invalid value is provided. - ? 0.5f : mLetterboxHorizontalPositionMultiplier; + float getLetterboxHorizontalPositionMultiplier(boolean isInBookMode) { + if (isInBookMode) { + if (mLetterboxBookModePositionMultiplier < 0.0f + || mLetterboxBookModePositionMultiplier > 1.0f) { + Slog.w(TAG, + "mLetterboxBookModePositionMultiplier out of bounds (isInBookMode=true): " + + mLetterboxBookModePositionMultiplier); + // Default to left position if invalid value is provided. + return 0.0f; + } else { + return mLetterboxBookModePositionMultiplier; + } + } else { + if (mLetterboxHorizontalPositionMultiplier < 0.0f + || mLetterboxHorizontalPositionMultiplier > 1.0f) { + Slog.w(TAG, + "mLetterboxBookModePositionMultiplier out of bounds (isInBookMode=false):" + + mLetterboxBookModePositionMultiplier); + // Default to central position if invalid value is provided. + return 0.5f; + } else { + return mLetterboxHorizontalPositionMultiplier; + } + } } /* @@ -473,11 +517,18 @@ final class LetterboxConfiguration { * or via an ADB command. 0 corresponds to the top side of the screen and 1 to the * bottom side. */ - float getLetterboxVerticalPositionMultiplier() { - return (mLetterboxVerticalPositionMultiplier < 0.0f - || mLetterboxVerticalPositionMultiplier > 1.0f) - // Default to central position if invalid value is provided. - ? 0.5f : mLetterboxVerticalPositionMultiplier; + float getLetterboxVerticalPositionMultiplier(boolean isInTabletopMode) { + if (isInTabletopMode) { + return (mLetterboxTabletopModePositionMultiplier < 0.0f + || mLetterboxTabletopModePositionMultiplier > 1.0f) + // Default to top position if invalid value is provided. + ? 0.0f : mLetterboxTabletopModePositionMultiplier; + } else { + return (mLetterboxVerticalPositionMultiplier < 0.0f + || mLetterboxVerticalPositionMultiplier > 1.0f) + // Default to central position if invalid value is provided. + ? 0.5f : mLetterboxVerticalPositionMultiplier; + } } /** @@ -618,7 +669,8 @@ final class LetterboxConfiguration { */ void resetDefaultPositionForHorizontalReachability() { mDefaultPositionForHorizontalReachability = - readLetterboxHorizontalReachabilityPositionFromConfig(mContext); + readLetterboxHorizontalReachabilityPositionFromConfig(mContext, + false /* forBookMode */); } /** @@ -627,27 +679,34 @@ final class LetterboxConfiguration { */ void resetDefaultPositionForVerticalReachability() { mDefaultPositionForVerticalReachability = - readLetterboxVerticalReachabilityPositionFromConfig(mContext); + readLetterboxVerticalReachabilityPositionFromConfig(mContext, + false /* forTabletopMode */); } @LetterboxHorizontalReachabilityPosition - private static int readLetterboxHorizontalReachabilityPositionFromConfig(Context context) { + private static int readLetterboxHorizontalReachabilityPositionFromConfig(Context context, + boolean forBookMode) { int position = context.getResources().getInteger( - R.integer.config_letterboxDefaultPositionForHorizontalReachability); + forBookMode + ? R.integer.config_letterboxDefaultPositionForBookModeReachability + : R.integer.config_letterboxDefaultPositionForHorizontalReachability); return position == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT - || position == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER - || position == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT + || position == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER + || position == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT ? position : LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER; } @LetterboxVerticalReachabilityPosition - private static int readLetterboxVerticalReachabilityPositionFromConfig(Context context) { + private static int readLetterboxVerticalReachabilityPositionFromConfig(Context context, + boolean forTabletopMode) { int position = context.getResources().getInteger( - R.integer.config_letterboxDefaultPositionForVerticalReachability); + forTabletopMode + ? R.integer.config_letterboxDefaultPositionForTabletopModeReachability + : R.integer.config_letterboxDefaultPositionForVerticalReachability); return position == LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP || position == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER || position == LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM - ? position : LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER; + ? position : LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER; } /* @@ -656,9 +715,10 @@ final class LetterboxConfiguration { * * <p>The position multiplier is changed after each double tap in the letterbox area. */ - float getHorizontalMultiplierForReachability() { + float getHorizontalMultiplierForReachability(boolean isDeviceInBookMode) { final int letterboxPositionForHorizontalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability( + isDeviceInBookMode); switch (letterboxPositionForHorizontalReachability) { case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT: return 0.0f; @@ -679,9 +739,10 @@ final class LetterboxConfiguration { * * <p>The position multiplier is changed after each double tap in the letterbox area. */ - float getVerticalMultiplierForReachability() { + float getVerticalMultiplierForReachability(boolean isDeviceInTabletopMode) { final int letterboxPositionForVerticalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability( + isDeviceInTabletopMode); switch (letterboxPositionForVerticalReachability) { case LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP: return 0.0f; @@ -701,8 +762,9 @@ final class LetterboxConfiguration { * enabled. */ @LetterboxHorizontalReachabilityPosition - int getLetterboxPositionForHorizontalReachability() { - return mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability(); + int getLetterboxPositionForHorizontalReachability(boolean isInFullScreenBookMode) { + return mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability( + isInFullScreenBookMode); } /* @@ -710,8 +772,9 @@ final class LetterboxConfiguration { * enabled. */ @LetterboxVerticalReachabilityPosition - int getLetterboxPositionForVerticalReachability() { - return mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(); + int getLetterboxPositionForVerticalReachability(boolean isInFullScreenTabletopMode) { + return mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability( + isInFullScreenTabletopMode); } /** Returns a string representing the given {@link LetterboxHorizontalReachabilityPosition}. */ @@ -750,34 +813,41 @@ final class LetterboxConfiguration { * Changes letterbox position for horizontal reachability to the next available one on the * right side. */ - void movePositionForHorizontalReachabilityToNextRightStop() { - updatePositionForHorizontalReachability(prev -> Math.min( - prev + 1, LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT)); + void movePositionForHorizontalReachabilityToNextRightStop(boolean isDeviceInBookMode) { + updatePositionForHorizontalReachability(isDeviceInBookMode, prev -> Math.min( + prev + (isDeviceInBookMode ? 2 : 1), // Move 2 stops in book mode to avoid center. + LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT)); } /** * Changes letterbox position for horizontal reachability to the next available one on the left * side. */ - void movePositionForHorizontalReachabilityToNextLeftStop() { - updatePositionForHorizontalReachability(prev -> Math.max(prev - 1, 0)); + void movePositionForHorizontalReachabilityToNextLeftStop(boolean isDeviceInBookMode) { + updatePositionForHorizontalReachability(isDeviceInBookMode, prev -> Math.max( + prev - (isDeviceInBookMode ? 2 : 1), 0)); // Move 2 stops in book mode to avoid + // center. } /** * Changes letterbox position for vertical reachability to the next available one on the bottom * side. */ - void movePositionForVerticalReachabilityToNextBottomStop() { - updatePositionForVerticalReachability(prev -> Math.min( - prev + 1, LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM)); + void movePositionForVerticalReachabilityToNextBottomStop(boolean isDeviceInTabletopMode) { + updatePositionForVerticalReachability(isDeviceInTabletopMode, prev -> Math.min( + prev + (isDeviceInTabletopMode ? 2 : 1), // Move 2 stops in tabletop mode to avoid + // center. + LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM)); } /** * Changes letterbox position for vertical reachability to the next available one on the top * side. */ - void movePositionForVerticalReachabilityToNextTopStop() { - updatePositionForVerticalReachability(prev -> Math.max(prev - 1, 0)); + void movePositionForVerticalReachabilityToNextTopStop(boolean isDeviceInTabletopMode) { + updatePositionForVerticalReachability(isDeviceInTabletopMode, prev -> Math.max( + prev - (isDeviceInTabletopMode ? 2 : 1), 0)); // Move 2 stops in tabletop mode to + // avoid center. } /** @@ -854,25 +924,27 @@ final class LetterboxConfiguration { } /** Calculates a new letterboxPositionForHorizontalReachability value and updates the store */ - private void updatePositionForHorizontalReachability( + private void updatePositionForHorizontalReachability(boolean isDeviceInBookMode, Function<Integer, Integer> newHorizonalPositionFun) { final int letterboxPositionForHorizontalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability( + isDeviceInBookMode); final int nextHorizontalPosition = newHorizonalPositionFun.apply( letterboxPositionForHorizontalReachability); mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability( - nextHorizontalPosition); + isDeviceInBookMode, nextHorizontalPosition); } /** Calculates a new letterboxPositionForVerticalReachability value and updates the store */ - private void updatePositionForVerticalReachability( + private void updatePositionForVerticalReachability(boolean isDeviceInTabletopMode, Function<Integer, Integer> newVerticalPositionFun) { final int letterboxPositionForVerticalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability( + isDeviceInTabletopMode); final int nextVerticalPosition = newVerticalPositionFun.apply( letterboxPositionForVerticalReachability); mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability( - nextVerticalPosition); + isDeviceInTabletopMode, nextVerticalPosition); } // TODO(b/262378106): Cache runtime flag and implement DeviceConfig.OnPropertiesChangedListener diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java b/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java index 70639b16c828..4a99db594755 100644 --- a/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java +++ b/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java @@ -55,6 +55,8 @@ class LetterboxConfigurationPersister { private final Context mContext; private final Supplier<Integer> mDefaultHorizontalReachabilitySupplier; private final Supplier<Integer> mDefaultVerticalReachabilitySupplier; + private final Supplier<Integer> mDefaultBookModeReachabilitySupplier; + private final Supplier<Integer> mDefaultTabletopModeReachabilitySupplier; // Horizontal position of a center of the letterboxed app window which is global to prevent // "jumps" when switching between letterboxed apps. It's updated to reposition the app window @@ -64,6 +66,11 @@ class LetterboxConfigurationPersister { @LetterboxHorizontalReachabilityPosition private volatile int mLetterboxPositionForHorizontalReachability; + // The same as mLetterboxPositionForHorizontalReachability but used when the device is + // half-folded. + @LetterboxHorizontalReachabilityPosition + private volatile int mLetterboxPositionForBookModeReachability; + // Vertical position of a center of the letterboxed app window which is global to prevent // "jumps" when switching between letterboxed apps. It's updated to reposition the app window // in response to a double tap gesture (see LetterboxUiController#handleDoubleTap). Used in @@ -72,6 +79,11 @@ class LetterboxConfigurationPersister { @LetterboxVerticalReachabilityPosition private volatile int mLetterboxPositionForVerticalReachability; + // The same as mLetterboxPositionForVerticalReachability but used when the device is + // half-folded. + @LetterboxVerticalReachabilityPosition + private volatile int mLetterboxPositionForTabletopModeReachability; + @NonNull private final AtomicFile mConfigurationFile; @@ -83,9 +95,13 @@ class LetterboxConfigurationPersister { LetterboxConfigurationPersister(Context systemUiContext, Supplier<Integer> defaultHorizontalReachabilitySupplier, - Supplier<Integer> defaultVerticalReachabilitySupplier) { + Supplier<Integer> defaultVerticalReachabilitySupplier, + Supplier<Integer> defaultBookModeReachabilitySupplier, + Supplier<Integer> defaultTabletopModeReachabilitySupplier) { this(systemUiContext, defaultHorizontalReachabilitySupplier, defaultVerticalReachabilitySupplier, + defaultBookModeReachabilitySupplier, + defaultTabletopModeReachabilitySupplier, Environment.getDataSystemDirectory(), new PersisterQueue(), /* completionCallback */ null); } @@ -93,11 +109,18 @@ class LetterboxConfigurationPersister { @VisibleForTesting LetterboxConfigurationPersister(Context systemUiContext, Supplier<Integer> defaultHorizontalReachabilitySupplier, - Supplier<Integer> defaultVerticalReachabilitySupplier, File configFolder, + Supplier<Integer> defaultVerticalReachabilitySupplier, + Supplier<Integer> defaultBookModeReachabilitySupplier, + Supplier<Integer> defaultTabletopModeReachabilitySupplier, + File configFolder, PersisterQueue persisterQueue, @Nullable Consumer<String> completionCallback) { mContext = systemUiContext.createDeviceProtectedStorageContext(); mDefaultHorizontalReachabilitySupplier = defaultHorizontalReachabilitySupplier; mDefaultVerticalReachabilitySupplier = defaultVerticalReachabilitySupplier; + mDefaultBookModeReachabilitySupplier = + defaultBookModeReachabilitySupplier; + mDefaultTabletopModeReachabilitySupplier = + defaultTabletopModeReachabilitySupplier; mCompletionCallback = completionCallback; final File prefFiles = new File(configFolder, LETTERBOX_CONFIGURATION_FILENAME); mConfigurationFile = new AtomicFile(prefFiles); @@ -117,8 +140,12 @@ class LetterboxConfigurationPersister { * enabled. */ @LetterboxHorizontalReachabilityPosition - int getLetterboxPositionForHorizontalReachability() { - return mLetterboxPositionForHorizontalReachability; + int getLetterboxPositionForHorizontalReachability(boolean forBookMode) { + if (forBookMode) { + return mLetterboxPositionForBookModeReachability; + } else { + return mLetterboxPositionForHorizontalReachability; + } } /* @@ -126,31 +153,55 @@ class LetterboxConfigurationPersister { * enabled. */ @LetterboxVerticalReachabilityPosition - int getLetterboxPositionForVerticalReachability() { - return mLetterboxPositionForVerticalReachability; + int getLetterboxPositionForVerticalReachability(boolean forTabletopMode) { + if (forTabletopMode) { + return mLetterboxPositionForTabletopModeReachability; + } else { + return mLetterboxPositionForVerticalReachability; + } } /** * Updates letterboxPositionForVerticalReachability if different from the current value */ - void setLetterboxPositionForHorizontalReachability( + void setLetterboxPositionForHorizontalReachability(boolean forBookMode, int letterboxPositionForHorizontalReachability) { - if (mLetterboxPositionForHorizontalReachability - != letterboxPositionForHorizontalReachability) { - mLetterboxPositionForHorizontalReachability = - letterboxPositionForHorizontalReachability; - updateConfiguration(); + if (forBookMode) { + if (mLetterboxPositionForBookModeReachability + != letterboxPositionForHorizontalReachability) { + mLetterboxPositionForBookModeReachability = + letterboxPositionForHorizontalReachability; + updateConfiguration(); + } + } else { + if (mLetterboxPositionForHorizontalReachability + != letterboxPositionForHorizontalReachability) { + mLetterboxPositionForHorizontalReachability = + letterboxPositionForHorizontalReachability; + updateConfiguration(); + } } } /** * Updates letterboxPositionForVerticalReachability if different from the current value */ - void setLetterboxPositionForVerticalReachability( + void setLetterboxPositionForVerticalReachability(boolean forTabletopMode, int letterboxPositionForVerticalReachability) { - if (mLetterboxPositionForVerticalReachability != letterboxPositionForVerticalReachability) { - mLetterboxPositionForVerticalReachability = letterboxPositionForVerticalReachability; - updateConfiguration(); + if (forTabletopMode) { + if (mLetterboxPositionForTabletopModeReachability + != letterboxPositionForVerticalReachability) { + mLetterboxPositionForTabletopModeReachability = + letterboxPositionForVerticalReachability; + updateConfiguration(); + } + } else { + if (mLetterboxPositionForVerticalReachability + != letterboxPositionForVerticalReachability) { + mLetterboxPositionForVerticalReachability = + letterboxPositionForVerticalReachability; + updateConfiguration(); + } } } @@ -158,6 +209,10 @@ class LetterboxConfigurationPersister { void useDefaultValue() { mLetterboxPositionForHorizontalReachability = mDefaultHorizontalReachabilitySupplier.get(); mLetterboxPositionForVerticalReachability = mDefaultVerticalReachabilitySupplier.get(); + mLetterboxPositionForBookModeReachability = + mDefaultBookModeReachabilitySupplier.get(); + mLetterboxPositionForTabletopModeReachability = + mDefaultTabletopModeReachabilitySupplier.get(); } private void readCurrentConfiguration() { @@ -171,6 +226,10 @@ class LetterboxConfigurationPersister { letterboxData.letterboxPositionForHorizontalReachability; mLetterboxPositionForVerticalReachability = letterboxData.letterboxPositionForVerticalReachability; + mLetterboxPositionForBookModeReachability = + letterboxData.letterboxPositionForBookModeReachability; + mLetterboxPositionForTabletopModeReachability = + letterboxData.letterboxPositionForTabletopModeReachability; } catch (IOException ioe) { Slog.e(TAG, "Error reading from LetterboxConfigurationPersister. " @@ -192,6 +251,8 @@ class LetterboxConfigurationPersister { mPersisterQueue.addItem(new UpdateValuesCommand(mConfigurationFile, mLetterboxPositionForHorizontalReachability, mLetterboxPositionForVerticalReachability, + mLetterboxPositionForBookModeReachability, + mLetterboxPositionForTabletopModeReachability, mCompletionCallback), /* flush */ true); } @@ -221,13 +282,18 @@ class LetterboxConfigurationPersister { private final int mHorizontalReachability; private final int mVerticalReachability; + private final int mBookModeReachability; + private final int mTabletopModeReachability; UpdateValuesCommand(@NonNull AtomicFile fileToUpdate, int horizontalReachability, int verticalReachability, + int bookModeReachability, int tabletopModeReachability, @Nullable Consumer<String> onComplete) { mFileToUpdate = fileToUpdate; mHorizontalReachability = horizontalReachability; mVerticalReachability = verticalReachability; + mBookModeReachability = bookModeReachability; + mTabletopModeReachability = tabletopModeReachability; mOnComplete = onComplete; } @@ -237,6 +303,10 @@ class LetterboxConfigurationPersister { new WindowManagerProtos.LetterboxProto(); letterboxData.letterboxPositionForHorizontalReachability = mHorizontalReachability; letterboxData.letterboxPositionForVerticalReachability = mVerticalReachability; + letterboxData.letterboxPositionForBookModeReachability = + mBookModeReachability; + letterboxData.letterboxPositionForTabletopModeReachability = + mTabletopModeReachability; final byte[] bytes = WindowManagerProtos.LetterboxProto.toByteArray(letterboxData); FileOutputStream fos = null; diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index a53a5fc00b0c..9cb94c68583f 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -275,30 +275,62 @@ final class LetterboxUiController { && mActivityRecord.fillsParent(); } + // Check if we are in the given pose and in fullscreen mode. + // Note that we check the task rather than the parent as with ActivityEmbedding the parent might + // be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is + // actually fullscreen. + private boolean isDisplayFullScreenAndInPosture(DeviceStateController.FoldState state, + boolean isTabletop) { + Task task = mActivityRecord.getTask(); + return mActivityRecord.mDisplayContent != null + && mActivityRecord.mDisplayContent.getDisplayRotation().isDeviceInPosture(state, + isTabletop) + && task != null + && task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN; + } + + // Note that we check the task rather than the parent as with ActivityEmbedding the parent might + // be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is + // actually fullscreen. + private boolean isDisplayFullScreenAndSeparatingHinge() { + Task task = mActivityRecord.getTask(); + return mActivityRecord.mDisplayContent != null + && mActivityRecord.mDisplayContent.getDisplayRotation().isDisplaySeparatingHinge() + && task != null + && task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN; + } + + float getHorizontalPositionMultiplier(Configuration parentConfiguration) { // Don't check resolved configuration because it may not be updated yet during // configuration change. + boolean bookMode = isDisplayFullScreenAndInPosture( + DeviceStateController.FoldState.HALF_FOLDED, false /* isTabletop */); return isHorizontalReachabilityEnabled(parentConfiguration) // Using the last global dynamic position to avoid "jumps" when moving // between apps or activities. - ? mLetterboxConfiguration.getHorizontalMultiplierForReachability() - : mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier(); + ? mLetterboxConfiguration.getHorizontalMultiplierForReachability(bookMode) + : mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier(bookMode); } float getVerticalPositionMultiplier(Configuration parentConfiguration) { // Don't check resolved configuration because it may not be updated yet during // configuration change. + boolean tabletopMode = isDisplayFullScreenAndInPosture( + DeviceStateController.FoldState.HALF_FOLDED, true /* isTabletop */); return isVerticalReachabilityEnabled(parentConfiguration) // Using the last global dynamic position to avoid "jumps" when moving // between apps or activities. - ? mLetterboxConfiguration.getVerticalMultiplierForReachability() - : mLetterboxConfiguration.getLetterboxVerticalPositionMultiplier(); + ? mLetterboxConfiguration.getVerticalMultiplierForReachability(tabletopMode) + : mLetterboxConfiguration.getLetterboxVerticalPositionMultiplier(tabletopMode); } float getFixedOrientationLetterboxAspectRatio() { - return mActivityRecord.shouldCreateCompatDisplayInsets() - ? getDefaultMinAspectRatioForUnresizableApps() - : mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(); + return isDisplayFullScreenAndSeparatingHinge() + ? getSplitScreenAspectRatio() + : mActivityRecord.shouldCreateCompatDisplayInsets() + ? getDefaultMinAspectRatioForUnresizableApps() + : mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(); } private float getDefaultMinAspectRatioForUnresizableApps() { @@ -351,11 +383,13 @@ final class LetterboxUiController { return; } + boolean isInFullScreenBookMode = isDisplayFullScreenAndSeparatingHinge(); int letterboxPositionForHorizontalReachability = mLetterboxConfiguration - .getLetterboxPositionForHorizontalReachability(); + .getLetterboxPositionForHorizontalReachability(isInFullScreenBookMode); if (mLetterbox.getInnerFrame().left > x) { // Moving to the next stop on the left side of the app window: right > center > left. - mLetterboxConfiguration.movePositionForHorizontalReachabilityToNextLeftStop(); + mLetterboxConfiguration.movePositionForHorizontalReachabilityToNextLeftStop( + isInFullScreenBookMode); int changeToLog = letterboxPositionForHorizontalReachability == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER @@ -364,7 +398,8 @@ final class LetterboxUiController { logLetterboxPositionChange(changeToLog); } else if (mLetterbox.getInnerFrame().right < x) { // Moving to the next stop on the right side of the app window: left > center > right. - mLetterboxConfiguration.movePositionForHorizontalReachabilityToNextRightStop(); + mLetterboxConfiguration.movePositionForHorizontalReachabilityToNextRightStop( + isInFullScreenBookMode); int changeToLog = letterboxPositionForHorizontalReachability == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER @@ -388,11 +423,13 @@ final class LetterboxUiController { // Only react to clicks at the top and bottom of the letterboxed app window. return; } + boolean isInFullScreenTabletopMode = isDisplayFullScreenAndSeparatingHinge(); int letterboxPositionForVerticalReachability = mLetterboxConfiguration - .getLetterboxPositionForVerticalReachability(); + .getLetterboxPositionForVerticalReachability(isInFullScreenTabletopMode); if (mLetterbox.getInnerFrame().top > y) { // Moving to the next stop on the top side of the app window: bottom > center > top. - mLetterboxConfiguration.movePositionForVerticalReachabilityToNextTopStop(); + mLetterboxConfiguration.movePositionForVerticalReachabilityToNextTopStop( + isInFullScreenTabletopMode); int changeToLog = letterboxPositionForVerticalReachability == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER @@ -401,7 +438,8 @@ final class LetterboxUiController { logLetterboxPositionChange(changeToLog); } else if (mLetterbox.getInnerFrame().bottom < y) { // Moving to the next stop on the bottom side of the app window: top > center > bottom. - mLetterboxConfiguration.movePositionForVerticalReachabilityToNextBottomStop(); + mLetterboxConfiguration.movePositionForVerticalReachabilityToNextBottomStop( + isInFullScreenTabletopMode); int changeToLog = letterboxPositionForVerticalReachability == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER @@ -712,10 +750,10 @@ final class LetterboxUiController { + getVerticalPositionMultiplier(mActivityRecord.getParent().getConfiguration())); pw.println(prefix + " letterboxPositionForHorizontalReachability=" + LetterboxConfiguration.letterboxHorizontalReachabilityPositionToString( - mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability())); + mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability(false))); pw.println(prefix + " letterboxPositionForVerticalReachability=" + LetterboxConfiguration.letterboxVerticalReachabilityPositionToString( - mLetterboxConfiguration.getLetterboxPositionForVerticalReachability())); + mLetterboxConfiguration.getLetterboxPositionForVerticalReachability(false))); pw.println(prefix + " fixedOrientationLetterboxAspectRatio=" + mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio()); pw.println(prefix + " defaultMinAspectRatioForUnresizableApps=" @@ -780,14 +818,20 @@ final class LetterboxUiController { int positionToLog = APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION; if (isHorizontalReachabilityEnabled()) { int letterboxPositionForHorizontalReachability = getLetterboxConfiguration() - .getLetterboxPositionForHorizontalReachability(); + .getLetterboxPositionForHorizontalReachability( + isDisplayFullScreenAndInPosture( + DeviceStateController.FoldState.HALF_FOLDED, + false /* isTabletop */)); positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPosition( - letterboxPositionForHorizontalReachability); + letterboxPositionForHorizontalReachability); } else if (isVerticalReachabilityEnabled()) { int letterboxPositionForVerticalReachability = getLetterboxConfiguration() - .getLetterboxPositionForVerticalReachability(); + .getLetterboxPositionForVerticalReachability( + isDisplayFullScreenAndInPosture( + DeviceStateController.FoldState.HALF_FOLDED, + true /* isTabletop */)); positionToLog = letterboxVerticalReachabilityPositionToLetterboxPosition( - letterboxPositionForVerticalReachability); + letterboxPositionForVerticalReachability); } return positionToLog; } diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index 4e692e2d212a..85aa9425c4fd 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -1219,9 +1219,17 @@ public class WindowManagerShellCommand extends ShellCommand { pw.println("Corner radius: " + mLetterboxConfiguration.getLetterboxActivityCornersRadius()); pw.println("Horizontal position multiplier: " - + mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier()); + + mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier( + false /* isInBookMode */)); pw.println("Vertical position multiplier: " - + mLetterboxConfiguration.getLetterboxVerticalPositionMultiplier()); + + mLetterboxConfiguration.getLetterboxVerticalPositionMultiplier( + false /* isInTabletopMode */)); + pw.println("Horizontal position multiplier (book mode): " + + mLetterboxConfiguration.getLetterboxHorizontalPositionMultiplier( + true /* isInBookMode */)); + pw.println("Vertical position multiplier (tabletop mode): " + + mLetterboxConfiguration.getLetterboxVerticalPositionMultiplier( + true /* isInTabletopMode */)); pw.println("Aspect ratio: " + mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio()); pw.println("Default min aspect ratio for unresizable apps: " @@ -1238,10 +1246,10 @@ public class WindowManagerShellCommand extends ShellCommand { mLetterboxConfiguration.getDefaultPositionForVerticalReachability())); pw.println("Current position for horizontal reachability:" + LetterboxConfiguration.letterboxHorizontalReachabilityPositionToString( - mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability())); + mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability(false))); pw.println("Current position for vertical reachability:" + LetterboxConfiguration.letterboxVerticalReachabilityPositionToString( - mLetterboxConfiguration.getLetterboxPositionForVerticalReachability())); + mLetterboxConfiguration.getLetterboxPositionForVerticalReachability(false))); pw.println("Is education enabled: " + mLetterboxConfiguration.getIsEducationEnabled()); pw.println("Is using split screen aspect ratio as aspect ratio for unresizable apps: " diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java index 1be9de78cd27..51a7e747afce 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java @@ -67,6 +67,11 @@ public class LetterboxConfigurationPersisterTest { R.integer.config_letterboxDefaultPositionForHorizontalReachability), () -> mContext.getResources().getInteger( R.integer.config_letterboxDefaultPositionForVerticalReachability), + () -> mContext.getResources().getInteger( + R.integer.config_letterboxDefaultPositionForBookModeReachability), + () -> mContext.getResources().getInteger( + R.integer.config_letterboxDefaultPositionForTabletopModeReachability + ), mConfigFolder, mPersisterQueue, mQueueState); mQueueListener = queueEmpty -> mQueueState.onItemAdded(); mPersisterQueue.addListener(mQueueListener); @@ -84,14 +89,15 @@ public class LetterboxConfigurationPersisterTest { @Test public void test_whenStoreIsCreated_valuesAreDefaults() { final int positionForHorizontalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability( + false); final int defaultPositionForHorizontalReachability = mContext.getResources().getInteger( R.integer.config_letterboxDefaultPositionForHorizontalReachability); Assert.assertEquals(defaultPositionForHorizontalReachability, positionForHorizontalReachability); final int positionForVerticalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(false); final int defaultPositionForVerticalReachability = mContext.getResources().getInteger( R.integer.config_letterboxDefaultPositionForVerticalReachability); @@ -101,15 +107,16 @@ public class LetterboxConfigurationPersisterTest { @Test public void test_whenUpdatedWithNewValues_valuesAreWritten() { - mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability( + mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability(false, LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT); - mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability( + mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability(false, LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP); waitForCompletion(mPersisterQueue); final int newPositionForHorizontalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability( + false); final int newPositionForVerticalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(false); Assert.assertEquals(LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, newPositionForHorizontalReachability); Assert.assertEquals(LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, @@ -120,24 +127,24 @@ public class LetterboxConfigurationPersisterTest { public void test_whenUpdatedWithNewValues_valuesAreReadAfterRestart() { final PersisterQueue firstPersisterQueue = new PersisterQueue(); final LetterboxConfigurationPersister firstPersister = new LetterboxConfigurationPersister( - mContext, () -> -1, () -> -1, mContext.getFilesDir(), firstPersisterQueue, - mQueueState); + mContext, () -> -1, () -> -1, () -> -1, () -> -1, mContext.getFilesDir(), + firstPersisterQueue, mQueueState); firstPersister.start(); - firstPersister.setLetterboxPositionForHorizontalReachability( + firstPersister.setLetterboxPositionForHorizontalReachability(false, LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT); - firstPersister.setLetterboxPositionForVerticalReachability( + firstPersister.setLetterboxPositionForVerticalReachability(false, LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP); waitForCompletion(firstPersisterQueue); stopPersisterSafe(firstPersisterQueue); final PersisterQueue secondPersisterQueue = new PersisterQueue(); final LetterboxConfigurationPersister secondPersister = new LetterboxConfigurationPersister( - mContext, () -> -1, () -> -1, mContext.getFilesDir(), secondPersisterQueue, - mQueueState); + mContext, () -> -1, () -> -1, () -> -1, () -> -1, mContext.getFilesDir(), + secondPersisterQueue, mQueueState); secondPersister.start(); final int newPositionForHorizontalReachability = - secondPersister.getLetterboxPositionForHorizontalReachability(); + secondPersister.getLetterboxPositionForHorizontalReachability(false); final int newPositionForVerticalReachability = - secondPersister.getLetterboxPositionForVerticalReachability(); + secondPersister.getLetterboxPositionForVerticalReachability(false); Assert.assertEquals(LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, newPositionForHorizontalReachability); Assert.assertEquals(LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, @@ -149,15 +156,16 @@ public class LetterboxConfigurationPersisterTest { @Test public void test_whenUpdatedWithNewValuesAndDeleted_valuesAreDefaults() { - mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability( + mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability(false, LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT); - mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability( + mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability(false, LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP); waitForCompletion(mPersisterQueue); final int newPositionForHorizontalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability( + false); final int newPositionForVerticalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(false); Assert.assertEquals(LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, newPositionForHorizontalReachability); Assert.assertEquals(LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, @@ -165,14 +173,15 @@ public class LetterboxConfigurationPersisterTest { deleteConfiguration(mLetterboxConfigurationPersister, mPersisterQueue); waitForCompletion(mPersisterQueue); final int positionForHorizontalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability( + false); final int defaultPositionForHorizontalReachability = mContext.getResources().getInteger( R.integer.config_letterboxDefaultPositionForHorizontalReachability); Assert.assertEquals(defaultPositionForHorizontalReachability, positionForHorizontalReachability); final int positionForVerticalReachability = - mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(); + mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability(false); final int defaultPositionForVerticalReachability = mContext.getResources().getInteger( R.integer.config_letterboxDefaultPositionForVerticalReachability); diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java index c927f9e449d5..e19670458bb7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java @@ -26,6 +26,7 @@ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_RE import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -39,7 +40,8 @@ import androidx.test.filters.SmallTest; import org.junit.Before; import org.junit.Test; -import java.util.function.Consumer; +import java.util.Arrays; +import java.util.function.BiConsumer; @SmallTest @Presubmit @@ -58,20 +60,28 @@ public class LetterboxConfigurationTest { @Test public void test_whenReadingValues_storeIsInvoked() { - mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability(); - verify(mLetterboxConfigurationPersister).getLetterboxPositionForHorizontalReachability(); - mLetterboxConfiguration.getLetterboxPositionForVerticalReachability(); - verify(mLetterboxConfigurationPersister).getLetterboxPositionForVerticalReachability(); + for (boolean halfFoldPose : Arrays.asList(false, true)) { + mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability(halfFoldPose); + verify(mLetterboxConfigurationPersister).getLetterboxPositionForHorizontalReachability( + halfFoldPose); + mLetterboxConfiguration.getLetterboxPositionForVerticalReachability(halfFoldPose); + verify(mLetterboxConfigurationPersister).getLetterboxPositionForVerticalReachability( + halfFoldPose); + } } @Test public void test_whenSettingValues_updateConfigurationIsInvoked() { - mLetterboxConfiguration.movePositionForHorizontalReachabilityToNextRightStop(); - verify(mLetterboxConfigurationPersister).setLetterboxPositionForHorizontalReachability( - anyInt()); - mLetterboxConfiguration.movePositionForVerticalReachabilityToNextBottomStop(); - verify(mLetterboxConfigurationPersister).setLetterboxPositionForVerticalReachability( - anyInt()); + for (boolean halfFoldPose : Arrays.asList(false, true)) { + mLetterboxConfiguration.movePositionForHorizontalReachabilityToNextRightStop( + halfFoldPose); + verify(mLetterboxConfigurationPersister).setLetterboxPositionForHorizontalReachability( + eq(halfFoldPose), anyInt()); + mLetterboxConfiguration.movePositionForVerticalReachabilityToNextBottomStop( + halfFoldPose); + verify(mLetterboxConfigurationPersister).setLetterboxPositionForVerticalReachability( + eq(halfFoldPose), anyInt()); + } } @Test @@ -81,33 +91,65 @@ public class LetterboxConfigurationTest { /* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER, /* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, /* expectedTime */ 1, + /* halfFoldPose */ false, LetterboxConfiguration::movePositionForHorizontalReachabilityToNextLeftStop); assertForHorizontalMove( /* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER, /* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT, /* expectedTime */ 1, + /* halfFoldPose */ false, LetterboxConfiguration::movePositionForHorizontalReachabilityToNextRightStop); // Starting from left assertForHorizontalMove( /* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, /* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, /* expectedTime */ 2, + /* halfFoldPose */ false, LetterboxConfiguration::movePositionForHorizontalReachabilityToNextLeftStop); assertForHorizontalMove( /* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, /* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER, /* expectedTime */ 1, + /* halfFoldPose */ false, LetterboxConfiguration::movePositionForHorizontalReachabilityToNextRightStop); // Starting from right assertForHorizontalMove( /* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT, /* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT, /* expectedTime */ 2, + /* halfFoldPose */ false, LetterboxConfiguration::movePositionForHorizontalReachabilityToNextRightStop); assertForHorizontalMove( /* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT, /* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER, /* expectedTime */ 2, + /* halfFoldPose */ false, + LetterboxConfiguration::movePositionForHorizontalReachabilityToNextLeftStop); + // Starting from left - book mode + assertForHorizontalMove( + /* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, + /* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, + /* expectedTime */ 1, + /* halfFoldPose */ true, + LetterboxConfiguration::movePositionForHorizontalReachabilityToNextLeftStop); + assertForHorizontalMove( + /* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, + /* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT, + /* expectedTime */ 1, + /* halfFoldPose */ true, + LetterboxConfiguration::movePositionForHorizontalReachabilityToNextRightStop); + // Starting from right - book mode + assertForHorizontalMove( + /* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT, + /* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT, + /* expectedTime */ 2, + /* halfFoldPose */ true, + LetterboxConfiguration::movePositionForHorizontalReachabilityToNextRightStop); + assertForHorizontalMove( + /* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT, + /* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT, + /* expectedTime */ 2, + /* halfFoldPose */ true, LetterboxConfiguration::movePositionForHorizontalReachabilityToNextLeftStop); } @@ -118,55 +160,87 @@ public class LetterboxConfigurationTest { /* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER, /* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM, /* expectedTime */ 1, + /* halfFoldPose */ false, LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop); assertForVerticalMove( /* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER, /* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, /* expectedTime */ 1, + /* halfFoldPose */ false, LetterboxConfiguration::movePositionForVerticalReachabilityToNextTopStop); // Starting from top assertForVerticalMove( /* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, /* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER, /* expectedTime */ 1, + /* halfFoldPose */ false, LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop); assertForVerticalMove( /* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, /* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, /* expectedTime */ 2, + /* halfFoldPose */ false, LetterboxConfiguration::movePositionForVerticalReachabilityToNextTopStop); // Starting from bottom assertForVerticalMove( /* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM, /* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER, /* expectedTime */ 2, + /* halfFoldPose */ false, + LetterboxConfiguration::movePositionForVerticalReachabilityToNextTopStop); + assertForVerticalMove( + /* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM, + /* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM, + /* expectedTime */ 2, + /* halfFoldPose */ false, + LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop); + // Starting from top - tabletop mode + assertForVerticalMove( + /* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, + /* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM, + /* expectedTime */ 1, + /* halfFoldPose */ true, + LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop); + assertForVerticalMove( + /* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, + /* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, + /* expectedTime */ 1, + /* halfFoldPose */ true, + LetterboxConfiguration::movePositionForVerticalReachabilityToNextTopStop); + // Starting from bottom - tabletop mode + assertForVerticalMove( + /* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM, + /* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP, + /* expectedTime */ 2, + /* halfFoldPose */ true, LetterboxConfiguration::movePositionForVerticalReachabilityToNextTopStop); assertForVerticalMove( /* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM, /* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM, /* expectedTime */ 2, + /* halfFoldPose */ true, LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop); } private void assertForHorizontalMove(int from, int expected, int expectedTime, - Consumer<LetterboxConfiguration> move) { + boolean halfFoldPose, BiConsumer<LetterboxConfiguration, Boolean> move) { // We are in the current position - when(mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability()) + when(mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability(halfFoldPose)) .thenReturn(from); - move.accept(mLetterboxConfiguration); + move.accept(mLetterboxConfiguration, halfFoldPose); verify(mLetterboxConfigurationPersister, - times(expectedTime)).setLetterboxPositionForHorizontalReachability( + times(expectedTime)).setLetterboxPositionForHorizontalReachability(halfFoldPose, expected); } private void assertForVerticalMove(int from, int expected, int expectedTime, - Consumer<LetterboxConfiguration> move) { + boolean halfFoldPose, BiConsumer<LetterboxConfiguration, Boolean> move) { // We are in the current position - when(mLetterboxConfiguration.getLetterboxPositionForVerticalReachability()) + when(mLetterboxConfiguration.getLetterboxPositionForVerticalReachability(halfFoldPose)) .thenReturn(from); - move.accept(mLetterboxConfiguration); + move.accept(mLetterboxConfiguration, halfFoldPose); verify(mLetterboxConfigurationPersister, - times(expectedTime)).setLetterboxPositionForVerticalReachability( + times(expectedTime)).setLetterboxPositionForVerticalReachability(halfFoldPose, expected); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 94c33f27f651..7488e1c113ab 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; @@ -95,6 +96,7 @@ import androidx.test.filters.MediumTest; import com.android.internal.policy.SystemBarUtils; import com.android.internal.statusbar.LetterboxDetails; import com.android.server.statusbar.StatusBarManagerInternal; +import com.android.server.wm.DeviceStateController.FoldState; import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; @@ -2821,6 +2823,70 @@ public class SizeCompatTests extends WindowTestsBase { } @Test + public void testUpdateResolvedBoundsVerticalPosition_tabletop() { + + // Set up a display in portrait with a fixed-orientation LANDSCAPE app + setUpDisplaySizeWithApp(1400, 2800); + mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + mActivity.mWmService.mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier( + 1.0f /*letterboxVerticalPositionMultiplier*/); + prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE); + + Rect letterboxNoFold = new Rect(0, 2100, 1400, 2800); + assertEquals(letterboxNoFold, mActivity.getBounds()); + + // Make the activity full-screen + mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + + setFoldablePosture(true /* isHalfFolded */, true /* isTabletop */); + + Rect letterboxHalfFold = new Rect(0, 0, 1400, 700); + assertEquals(letterboxHalfFold, mActivity.getBounds()); + + setFoldablePosture(false /* isHalfFolded */, false /* isTabletop */); + + assertEquals(letterboxNoFold, mActivity.getBounds()); + + } + + @Test + public void testUpdateResolvedBoundsHorizontalPosition_book() { + + // Set up a display in landscape with a fixed-orientation PORTRAIT app + setUpDisplaySizeWithApp(2800, 1400); + mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier( + 1.0f /*letterboxVerticalPositionMultiplier*/); + prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); + + Rect letterboxNoFold = new Rect(2100, 0, 2800, 1400); + assertEquals(letterboxNoFold, mActivity.getBounds()); + + // Make the activity full-screen + mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + + setFoldablePosture(true /* isHalfFolded */, false /* isTabletop */); + + Rect letterboxHalfFold = new Rect(0, 0, 700, 1400); + assertEquals(letterboxHalfFold, mActivity.getBounds()); + + setFoldablePosture(false /* isHalfFolded */, false /* isTabletop */); + + assertEquals(letterboxNoFold, mActivity.getBounds()); + + } + + private void setFoldablePosture(boolean isHalfFolded, boolean isTabletop) { + final DisplayRotation r = mActivity.mDisplayContent.getDisplayRotation(); + doReturn(isHalfFolded).when(r).isDisplaySeparatingHinge(); + doReturn(false).when(r).isDeviceInPosture(any(FoldState.class), anyBoolean()); + if (isHalfFolded) { + doReturn(true).when(r).isDeviceInPosture(FoldState.HALF_FOLDED, isTabletop); + } + mActivity.recomputeConfiguration(); + } + + @Test public void testUpdateResolvedBoundsPosition_alignToTop() { final int notchHeight = 100; final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2800) |