summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author William Osborn <willosborn@google.com> 2022-10-12 16:40:12 +0100
committer William Osborn <willosborn@google.com> 2022-12-19 11:48:50 +0000
commitfcb3add08f40bfbded442d40b79fc3a57ae71e2a (patch)
tree2eca1e8450a28d78a1e1cc11fb99cf3048dde8e7
parent596e3f9025a9fdd048a76b0988954a2eb518b142 (diff)
Letterboxing improvements for tabletop mode
Move letterboxed apps to the top screen and resize when in tabletop pose and move to the left for book mode. Also allow double-tapping to move the app to the alternative half of the screen. Bug: 245740388 Test: locally tested Change-Id: I14434ad23091de3957f04284e03da8701f159fa4
-rw-r--r--core/res/res/values/config.xml45
-rw-r--r--core/res/res/values/symbols.xml6
-rw-r--r--data/etc/services.core.protolog.json12
-rw-r--r--proto/src/windowmanager.proto4
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java12
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java78
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java166
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java102
-rw-r--r--services/core/java/com/android/server/wm/LetterboxUiController.java82
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java16
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationPersisterTest.java49
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxConfigurationTest.java112
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java66
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)