summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java10
-rw-r--r--services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java27
-rw-r--r--services/core/java/com/android/server/wm/AppCompatController.java25
-rw-r--r--services/core/java/com/android/server/wm/AppCompatDeviceStateQuery.java64
-rw-r--r--services/core/java/com/android/server/wm/AppCompatOverrides.java18
-rw-r--r--services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java343
-rw-r--r--services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java153
-rw-r--r--services/core/java/com/android/server/wm/AppCompatUtils.java19
-rw-r--r--services/core/java/com/android/server/wm/LetterboxUiController.java401
-rw-r--r--services/core/java/com/android/server/wm/Task.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java68
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java45
13 files changed, 715 insertions, 462 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 4085ec90c95e..fb2bf39c0b7b 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -1612,7 +1612,8 @@ class ActivityMetricsLogger {
int positionToLog = APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__NOT_LETTERBOXED_POSITION;
if (isAppCompateStateChangedToLetterboxed(state)) {
- positionToLog = activity.mLetterboxUiController.getLetterboxPositionForLogging();
+ positionToLog = activity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .getLetterboxPositionForLogging();
}
FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPAT_STATE_CHANGED,
packageUid, state, positionToLog);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8a768c0ed84d..c5fc2d2749e6 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -8633,8 +8633,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
/**
* 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)}
+ * AppCompatReachabilityOverrides#getHorizontalPositionMultiplier(Configuration)} and
+ * {@link AppCompatReachabilityOverrides#getVerticalPositionMultiplier(Configuration)}
* <p>
* Note that this is the final step that can change the resolved bounds. After this method
* is called, the position of the bounds will be moved to app space as sandboxing if the
@@ -8663,11 +8663,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
} else {
navBarInsets = Insets.NONE;
}
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mAppCompatController.getAppCompatReachabilityOverrides();
// Horizontal position
int offsetX = 0;
if (parentBounds.width() != screenResolvedBoundsWidth) {
if (screenResolvedBoundsWidth <= parentAppBoundsWidth) {
- float positionMultiplier = mLetterboxUiController.getHorizontalPositionMultiplier(
+ float positionMultiplier = reachabilityOverrides.getHorizontalPositionMultiplier(
newParentConfiguration);
// If in immersive mode, always align to right and overlap right insets (task bar)
// as they are transient and hidden. This removes awkward right spacing.
@@ -8688,7 +8690,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
int offsetY = 0;
if (parentBoundsHeight != screenResolvedBoundsHeight) {
if (screenResolvedBoundsHeight <= parentAppBoundsHeight) {
- float positionMultiplier = mLetterboxUiController.getVerticalPositionMultiplier(
+ float positionMultiplier = reachabilityOverrides.getVerticalPositionMultiplier(
newParentConfiguration);
// If in immersive mode, always align to bottom and overlap bottom insets (nav bar,
// task bar) as they are transient and hidden. This removes awkward bottom spacing.
diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
index 25cb134a7c52..d2f3d1db16a7 100644
--- a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
@@ -50,8 +50,6 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.utils.OptPropFactory;
-import java.util.function.Function;
-
/**
* Encapsulates app compat configurations and overrides related to aspect ratio.
*/
@@ -76,20 +74,20 @@ class AppCompatAspectRatioOverrides {
@NonNull
private final OptPropFactory.OptProp mAllowOrientationOverrideOptProp;
@NonNull
- private final Function<Boolean, Boolean> mIsDisplayFullScreenAndInPostureProvider;
+ private final AppCompatDeviceStateQuery mAppCompatDeviceStateQuery;
@NonNull
- private final Function<Configuration, Float> mGetHorizontalPositionMultiplierProvider;
+ private final AppCompatReachabilityOverrides mAppCompatReachabilityOverrides;
AppCompatAspectRatioOverrides(@NonNull ActivityRecord activityRecord,
@NonNull AppCompatConfiguration appCompatConfiguration,
@NonNull OptPropFactory optPropBuilder,
- @NonNull Function<Boolean, Boolean> isDisplayFullScreenAndInPostureProvider,
- @NonNull Function<Configuration, Float> getHorizontalPositionMultiplierProvider) {
+ @NonNull AppCompatDeviceStateQuery appCompatDeviceStateQuery,
+ @NonNull AppCompatReachabilityOverrides appCompatReachabilityOverrides) {
mActivityRecord = activityRecord;
mAppCompatConfiguration = appCompatConfiguration;
+ mAppCompatDeviceStateQuery = appCompatDeviceStateQuery;
mUserAspectRatioState = new UserAspectRatioState();
- mIsDisplayFullScreenAndInPostureProvider = isDisplayFullScreenAndInPostureProvider;
- mGetHorizontalPositionMultiplierProvider = getHorizontalPositionMultiplierProvider;
+ mAppCompatReachabilityOverrides = appCompatReachabilityOverrides;
mAllowMinAspectRatioOverrideOptProp = optPropBuilder.create(
PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE);
mAllowUserAspectRatioOverrideOptProp = optPropBuilder.create(
@@ -245,12 +243,13 @@ class AppCompatAspectRatioOverrides {
}
private boolean shouldUseSplitScreenAspectRatio(@NonNull Configuration parentConfiguration) {
- final boolean isBookMode = mIsDisplayFullScreenAndInPostureProvider
- .apply(/* isTabletop */false);
- final boolean isNotCenteredHorizontally = mGetHorizontalPositionMultiplierProvider.apply(
- parentConfiguration) != LETTERBOX_POSITION_MULTIPLIER_CENTER;
- final boolean isTabletopMode = mIsDisplayFullScreenAndInPostureProvider
- .apply(/* isTabletop */ true);
+ final boolean isBookMode = mAppCompatDeviceStateQuery
+ .isDisplayFullScreenAndInPosture(/* isTabletop */false);
+ final boolean isNotCenteredHorizontally =
+ mAppCompatReachabilityOverrides.getHorizontalPositionMultiplier(parentConfiguration)
+ != LETTERBOX_POSITION_MULTIPLIER_CENTER;
+ final boolean isTabletopMode = mAppCompatDeviceStateQuery
+ .isDisplayFullScreenAndInPosture(/* isTabletop */ true);
final boolean isLandscape = isFixedOrientationLandscape(
mActivityRecord.getOverrideOrientation());
final AppCompatCameraOverrides cameraOverrides =
diff --git a/services/core/java/com/android/server/wm/AppCompatController.java b/services/core/java/com/android/server/wm/AppCompatController.java
index 54223b609449..d38edfc39a8a 100644
--- a/services/core/java/com/android/server/wm/AppCompatController.java
+++ b/services/core/java/com/android/server/wm/AppCompatController.java
@@ -35,7 +35,11 @@ class AppCompatController {
@NonNull
private final AppCompatAspectRatioPolicy mAppCompatAspectRatioPolicy;
@NonNull
+ private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy;
+ @NonNull
private final AppCompatOverrides mAppCompatOverrides;
+ @NonNull
+ private final AppCompatDeviceStateQuery mAppCompatDeviceStateQuery;
AppCompatController(@NonNull WindowManagerService wmService,
@NonNull ActivityRecord activityRecord) {
@@ -43,13 +47,16 @@ class AppCompatController {
final PackageManager packageManager = wmService.mContext.getPackageManager();
final OptPropFactory optPropBuilder = new OptPropFactory(packageManager,
activityRecord.packageName);
+ mAppCompatDeviceStateQuery = new AppCompatDeviceStateQuery(activityRecord);
mTransparentPolicy = new TransparentPolicy(activityRecord,
wmService.mAppCompatConfiguration);
mAppCompatOverrides = new AppCompatOverrides(activityRecord,
- wmService.mAppCompatConfiguration, optPropBuilder);
+ wmService.mAppCompatConfiguration, optPropBuilder, mAppCompatDeviceStateQuery);
mOrientationPolicy = new AppCompatOrientationPolicy(activityRecord, mAppCompatOverrides);
mAppCompatAspectRatioPolicy = new AppCompatAspectRatioPolicy(activityRecord,
mTransparentPolicy, mAppCompatOverrides);
+ mAppCompatReachabilityPolicy = new AppCompatReachabilityPolicy(mActivityRecord,
+ wmService.mAppCompatConfiguration);
}
@NonNull
@@ -101,7 +108,23 @@ class AppCompatController {
}
@NonNull
+ AppCompatReachabilityPolicy getAppCompatReachabilityPolicy() {
+ return mAppCompatReachabilityPolicy;
+ }
+
+ @NonNull
AppCompatFocusOverrides getAppCompatFocusOverrides() {
return mAppCompatOverrides.getAppCompatFocusOverrides();
}
+
+ @NonNull
+ AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() {
+ return mAppCompatOverrides.getAppCompatReachabilityOverrides();
+ }
+
+ @NonNull
+ AppCompatDeviceStateQuery getAppCompatDeviceStateQuery() {
+ return mAppCompatDeviceStateQuery;
+ }
+
}
diff --git a/services/core/java/com/android/server/wm/AppCompatDeviceStateQuery.java b/services/core/java/com/android/server/wm/AppCompatDeviceStateQuery.java
new file mode 100644
index 000000000000..3abea24c530a
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppCompatDeviceStateQuery.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import android.annotation.NonNull;
+
+/**
+ * Provides information about the current state of the display in relation of
+ * fold/unfold and other positions.
+ */
+class AppCompatDeviceStateQuery {
+
+ @NonNull
+ final ActivityRecord mActivityRecord;
+
+ AppCompatDeviceStateQuery(@NonNull ActivityRecord activityRecord) {
+ mActivityRecord = activityRecord;
+ }
+
+ /**
+ * 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. If display is still in transition e.g. unfolding, don't return true
+ * for HALF_FOLDED state or app will flicker.
+ */
+ boolean isDisplayFullScreenAndInPosture(boolean isTabletop) {
+ final Task task = mActivityRecord.getTask();
+ final DisplayContent dc = mActivityRecord.mDisplayContent;
+ return dc != null && task != null && !dc.inTransition()
+ && dc.getDisplayRotation().isDeviceInPosture(
+ DeviceStateController.DeviceState.HALF_FOLDED, isTabletop)
+ && 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.
+ */
+ boolean isDisplayFullScreenAndSeparatingHinge() {
+ final Task task = mActivityRecord.getTask();
+ return mActivityRecord.mDisplayContent != null && task != null
+ && mActivityRecord.mDisplayContent.getDisplayRotation().isDisplaySeparatingHinge()
+ && task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AppCompatOverrides.java b/services/core/java/com/android/server/wm/AppCompatOverrides.java
index 445001178d26..80bbee3dd78d 100644
--- a/services/core/java/com/android/server/wm/AppCompatOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatOverrides.java
@@ -35,19 +35,22 @@ public class AppCompatOverrides {
private final AppCompatFocusOverrides mAppCompatFocusOverrides;
@NonNull
private final AppCompatResizeOverrides mAppCompatResizeOverrides;
+ @NonNull
+ private final AppCompatReachabilityOverrides mAppCompatReachabilityOverrides;
AppCompatOverrides(@NonNull ActivityRecord activityRecord,
@NonNull AppCompatConfiguration appCompatConfiguration,
- @NonNull OptPropFactory optPropBuilder) {
+ @NonNull OptPropFactory optPropBuilder,
+ @NonNull AppCompatDeviceStateQuery appCompatDeviceStateQuery) {
mAppCompatCameraOverrides = new AppCompatCameraOverrides(activityRecord,
appCompatConfiguration, optPropBuilder);
mAppCompatOrientationOverrides = new AppCompatOrientationOverrides(activityRecord,
appCompatConfiguration, optPropBuilder, mAppCompatCameraOverrides);
- // TODO(b/341903757) Remove BooleanSuppliers after fixing dependency with reachability.
+ mAppCompatReachabilityOverrides = new AppCompatReachabilityOverrides(activityRecord,
+ appCompatConfiguration, appCompatDeviceStateQuery);
mAppCompatAspectRatioOverrides = new AppCompatAspectRatioOverrides(activityRecord,
- appCompatConfiguration, optPropBuilder,
- activityRecord.mLetterboxUiController::isDisplayFullScreenAndInPosture,
- activityRecord.mLetterboxUiController::getHorizontalPositionMultiplier);
+ appCompatConfiguration, optPropBuilder, appCompatDeviceStateQuery,
+ mAppCompatReachabilityOverrides);
mAppCompatFocusOverrides = new AppCompatFocusOverrides(activityRecord,
appCompatConfiguration, optPropBuilder);
mAppCompatResizeOverrides = new AppCompatResizeOverrides(activityRecord, optPropBuilder);
@@ -77,4 +80,9 @@ public class AppCompatOverrides {
AppCompatResizeOverrides getAppCompatResizeOverrides() {
return mAppCompatResizeOverrides;
}
+
+ @NonNull
+ AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() {
+ return mAppCompatReachabilityOverrides;
+ }
}
diff --git a/services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java b/services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java
new file mode 100644
index 000000000000..b9bdc325cf98
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__LEFT;
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__RIGHT;
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__TOP;
+import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
+
+import android.annotation.NonNull;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.window.flags.Flags;
+
+/**
+ * Encapsulate overrides and configurations about app compat reachability.
+ */
+class AppCompatReachabilityOverrides {
+
+ @NonNull
+ private final ActivityRecord mActivityRecord;
+ @NonNull
+ private final AppCompatConfiguration mAppCompatConfiguration;
+ @NonNull
+ private final AppCompatDeviceStateQuery mAppCompatDeviceStateQuery;
+ @NonNull
+ private final ReachabilityState mReachabilityState;
+
+ AppCompatReachabilityOverrides(@NonNull ActivityRecord activityRecord,
+ @NonNull AppCompatConfiguration appCompatConfiguration,
+ @NonNull AppCompatDeviceStateQuery appCompatDeviceStateQuery) {
+ mActivityRecord = activityRecord;
+ mAppCompatConfiguration = appCompatConfiguration;
+ mAppCompatDeviceStateQuery = appCompatDeviceStateQuery;
+ mReachabilityState = new ReachabilityState();
+ }
+
+ boolean isFromDoubleTap() {
+ return mReachabilityState.isFromDoubleTap();
+ }
+
+ boolean isDoubleTapEvent() {
+ return mReachabilityState.mIsDoubleTapEvent;
+ }
+
+ void setDoubleTapEvent() {
+ mReachabilityState.mIsDoubleTapEvent = true;
+ }
+
+ /**
+ * Provides the multiplier to use when calculating the position of a letterboxed app after
+ * an horizontal reachability event (double tap). The method takes the current state of the
+ * device (e.g. device in book mode) into account.
+ * </p>
+ * @param parentConfiguration The parent {@link Configuration}.
+ * @return The value to use for calculating the letterbox horizontal position.
+ */
+ float getHorizontalPositionMultiplier(@NonNull Configuration parentConfiguration) {
+ // Don't check resolved configuration because it may not be updated yet during
+ // configuration change.
+ boolean bookModeEnabled = isFullScreenAndBookModeEnabled();
+ return isHorizontalReachabilityEnabled(parentConfiguration)
+ // Using the last global dynamic position to avoid "jumps" when moving
+ // between apps or activities.
+ ? mAppCompatConfiguration.getHorizontalMultiplierForReachability(bookModeEnabled)
+ : mAppCompatConfiguration.getLetterboxHorizontalPositionMultiplier(bookModeEnabled);
+ }
+
+ /**
+ * Provides the multiplier to use when calculating the position of a letterboxed app after
+ * a vertical reachability event (double tap). The method takes the current state of the
+ * device (e.g. device posture) into account.
+ * </p>
+ * @param parentConfiguration The parent {@link Configuration}.
+ * @return The value to use for calculating the letterbox horizontal position.
+ */
+ float getVerticalPositionMultiplier(@NonNull Configuration parentConfiguration) {
+ // Don't check resolved configuration because it may not be updated yet during
+ // configuration change.
+ boolean tabletopMode = mAppCompatDeviceStateQuery
+ .isDisplayFullScreenAndInPosture(/* isTabletop */ true);
+ return isVerticalReachabilityEnabled(parentConfiguration)
+ // Using the last global dynamic position to avoid "jumps" when moving
+ // between apps or activities.
+ ? mAppCompatConfiguration.getVerticalMultiplierForReachability(tabletopMode)
+ : mAppCompatConfiguration.getLetterboxVerticalPositionMultiplier(tabletopMode);
+ }
+
+ @VisibleForTesting
+ boolean isHorizontalReachabilityEnabled() {
+ return isHorizontalReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
+ }
+
+ @VisibleForTesting
+ boolean isVerticalReachabilityEnabled() {
+ return isVerticalReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
+ }
+
+ boolean isLetterboxDoubleTapEducationEnabled() {
+ return isHorizontalReachabilityEnabled() || isVerticalReachabilityEnabled();
+ }
+
+ @AppCompatConfiguration.LetterboxVerticalReachabilityPosition
+ int getLetterboxPositionForVerticalReachability() {
+ final boolean isInFullScreenTabletopMode =
+ mAppCompatDeviceStateQuery.isDisplayFullScreenAndSeparatingHinge();
+ return mAppCompatConfiguration.getLetterboxPositionForVerticalReachability(
+ isInFullScreenTabletopMode);
+ }
+
+ @AppCompatConfiguration.LetterboxHorizontalReachabilityPosition
+ int getLetterboxPositionForHorizontalReachability() {
+ final boolean isInFullScreenBookMode = isFullScreenAndBookModeEnabled();
+ return mAppCompatConfiguration.getLetterboxPositionForHorizontalReachability(
+ isInFullScreenBookMode);
+ }
+
+ int getLetterboxPositionForLogging() {
+ int positionToLog = APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION;
+ if (isHorizontalReachabilityEnabled()) {
+ int letterboxPositionForHorizontalReachability = mAppCompatConfiguration
+ .getLetterboxPositionForHorizontalReachability(mAppCompatDeviceStateQuery
+ .isDisplayFullScreenAndInPosture(/* isTabletop */ false));
+ positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPositionForLogging(
+ letterboxPositionForHorizontalReachability);
+ } else if (isVerticalReachabilityEnabled()) {
+ int letterboxPositionForVerticalReachability = mAppCompatConfiguration
+ .getLetterboxPositionForVerticalReachability(mAppCompatDeviceStateQuery
+ .isDisplayFullScreenAndInPosture(/* isTabletop */ true));
+ positionToLog = letterboxVerticalReachabilityPositionToLetterboxPositionForLogging(
+ letterboxPositionForVerticalReachability);
+ }
+ return positionToLog;
+ }
+
+ /**
+ * @return {@value true} if the vertical reachability should be allowed in case of
+ * thin letterboxing.
+ */
+ boolean allowVerticalReachabilityForThinLetterbox() {
+ if (!Flags.disableThinLetterboxingPolicy()) {
+ return true;
+ }
+ // When the flag is enabled we allow vertical reachability only if the
+ // app is not thin letterboxed vertically.
+ return !isVerticalThinLetterboxed();
+ }
+
+ /**
+ * @return {@value true} if the horizontal reachability should be enabled in case of
+ * thin letterboxing.
+ */
+ boolean allowHorizontalReachabilityForThinLetterbox() {
+ if (!Flags.disableThinLetterboxingPolicy()) {
+ return true;
+ }
+ // When the flag is enabled we allow horizontal reachability only if the
+ // app is not thin pillarboxed.
+ return !isHorizontalThinLetterboxed();
+ }
+
+ /**
+ * @return {@value true} if the resulting app is letterboxed in a way defined as thin.
+ */
+ boolean isVerticalThinLetterboxed() {
+ final int thinHeight = mAppCompatConfiguration.getThinLetterboxHeightPx();
+ if (thinHeight < 0) {
+ return false;
+ }
+ final Task task = mActivityRecord.getTask();
+ if (task == null) {
+ return false;
+ }
+ final int padding = Math.abs(
+ task.getBounds().height() - mActivityRecord.getBounds().height()) / 2;
+ return padding <= thinHeight;
+ }
+
+ /**
+ * @return {@value true} if the resulting app is pillarboxed in a way defined as thin.
+ */
+ boolean isHorizontalThinLetterboxed() {
+ final int thinWidth = mAppCompatConfiguration.getThinLetterboxWidthPx();
+ if (thinWidth < 0) {
+ return false;
+ }
+ final Task task = mActivityRecord.getTask();
+ if (task == null) {
+ return false;
+ }
+ final int padding = Math.abs(
+ task.getBounds().width() - mActivityRecord.getBounds().width()) / 2;
+ return padding <= thinWidth;
+ }
+
+ // 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;
+ }
+
+ private int letterboxHorizontalReachabilityPositionToLetterboxPositionForLogging(
+ @AppCompatConfiguration.LetterboxHorizontalReachabilityPosition int position) {
+ switch (position) {
+ case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__LEFT;
+ case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
+ case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__RIGHT;
+ default:
+ throw new AssertionError(
+ "Unexpected letterbox horizontal reachability position type: "
+ + position);
+ }
+ }
+
+ private int letterboxVerticalReachabilityPositionToLetterboxPositionForLogging(
+ @AppCompatConfiguration.LetterboxVerticalReachabilityPosition int position) {
+ switch (position) {
+ case LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__TOP;
+ case LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
+ case LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM:
+ return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
+ default:
+ throw new AssertionError(
+ "Unexpected letterbox vertical reachability position type: "
+ + position);
+ }
+ }
+
+ private boolean isFullScreenAndBookModeEnabled() {
+ return mAppCompatDeviceStateQuery.isDisplayFullScreenAndInPosture(/* isTabletop */ false)
+ && mAppCompatConfiguration.getIsAutomaticReachabilityInBookModeEnabled();
+ }
+
+ /**
+ * Whether horizontal reachability is enabled for an activity in the current configuration.
+ *
+ * <p>Conditions that needs to be met:
+ * <ul>
+ * <li>Windowing mode is fullscreen.
+ * <li>Horizontal Reachability is enabled.
+ * <li>First top opaque activity fills parent vertically, but not horizontally.
+ * </ul>
+ */
+ private boolean isHorizontalReachabilityEnabled(@NonNull Configuration parentConfiguration) {
+ if (!allowHorizontalReachabilityForThinLetterbox()) {
+ return false;
+ }
+ final Rect parentAppBoundsOverride = mActivityRecord.getParentAppBoundsOverride();
+ final Rect parentAppBounds = parentAppBoundsOverride != null
+ ? parentAppBoundsOverride : parentConfiguration.windowConfiguration.getAppBounds();
+ // Use screen resolved bounds which uses resolved bounds or size compat bounds
+ // as activity bounds can sometimes be empty
+ final Rect opaqueActivityBounds = mActivityRecord.mAppCompatController
+ .getTransparentPolicy().getFirstOpaqueActivity()
+ .map(ActivityRecord::getScreenResolvedBounds)
+ .orElse(mActivityRecord.getScreenResolvedBounds());
+ return mAppCompatConfiguration.getIsHorizontalReachabilityEnabled()
+ && parentConfiguration.windowConfiguration.getWindowingMode()
+ == WINDOWING_MODE_FULLSCREEN
+ // Check whether the activity fills the parent vertically.
+ && parentAppBounds.height() <= opaqueActivityBounds.height()
+ && parentAppBounds.width() > opaqueActivityBounds.width();
+ }
+
+ /**
+ * Whether vertical reachability is enabled for an activity in the current configuration.
+ *
+ * <p>Conditions that needs to be met:
+ * <ul>
+ * <li>Windowing mode is fullscreen.
+ * <li>Vertical Reachability is enabled.
+ * <li>First top opaque activity fills parent horizontally but not vertically.
+ * </ul>
+ */
+ private boolean isVerticalReachabilityEnabled(@NonNull Configuration parentConfiguration) {
+ if (!allowVerticalReachabilityForThinLetterbox()) {
+ return false;
+ }
+ final Rect parentAppBoundsOverride = mActivityRecord.getParentAppBoundsOverride();
+ final Rect parentAppBounds = parentAppBoundsOverride != null
+ ? parentAppBoundsOverride : parentConfiguration.windowConfiguration.getAppBounds();
+ // Use screen resolved bounds which uses resolved bounds or size compat bounds
+ // as activity bounds can sometimes be empty.
+ final Rect opaqueActivityBounds = mActivityRecord.mAppCompatController
+ .getTransparentPolicy().getFirstOpaqueActivity()
+ .map(ActivityRecord::getScreenResolvedBounds)
+ .orElse(mActivityRecord.getScreenResolvedBounds());
+ return mAppCompatConfiguration.getIsVerticalReachabilityEnabled()
+ && parentConfiguration.windowConfiguration.getWindowingMode()
+ == WINDOWING_MODE_FULLSCREEN
+ // Check whether the activity fills the parent horizontally.
+ && parentAppBounds.width() <= opaqueActivityBounds.width()
+ && parentAppBounds.height() > opaqueActivityBounds.height();
+ }
+
+ private static class ReachabilityState {
+ // If the current event is a double tap.
+ private boolean mIsDoubleTapEvent;
+
+ boolean isFromDoubleTap() {
+ final boolean isFromDoubleTap = mIsDoubleTapEvent;
+ mIsDoubleTapEvent = false;
+ return isFromDoubleTap;
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java b/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java
new file mode 100644
index 000000000000..e4e765421c06
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AppCompatReachabilityPolicy.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__BOTTOM_TO_CENTER;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_BOTTOM;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_LEFT;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_RIGHT;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_TOP;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__LEFT_TO_CENTER;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__RIGHT_TO_CENTER;
+import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__TOP_TO_CENTER;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
+
+import android.annotation.NonNull;
+import android.graphics.Rect;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.function.Supplier;
+
+/**
+ * Encapsulate logic about app compat reachability.
+ */
+class AppCompatReachabilityPolicy {
+
+ @NonNull
+ private final ActivityRecord mActivityRecord;
+ @NonNull
+ private final AppCompatConfiguration mAppCompatConfiguration;
+
+ AppCompatReachabilityPolicy(@NonNull ActivityRecord activityRecord,
+ @NonNull AppCompatConfiguration appCompatConfiguration) {
+ mActivityRecord = activityRecord;
+ mAppCompatConfiguration = appCompatConfiguration;
+ }
+
+ @VisibleForTesting
+ void handleHorizontalDoubleTap(int x, @NonNull Supplier<Rect> innerFrameSupplier) {
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides();
+ if (!reachabilityOverrides.isHorizontalReachabilityEnabled()
+ || mActivityRecord.isInTransition()) {
+ return;
+ }
+ final Rect letterboxInnerFrame = innerFrameSupplier.get();
+ if (letterboxInnerFrame.left <= x && letterboxInnerFrame.right >= x) {
+ // Only react to clicks at the sides of the letterboxed app window.
+ return;
+ }
+ final AppCompatDeviceStateQuery deviceStateQuery = mActivityRecord.mAppCompatController
+ .getAppCompatDeviceStateQuery();
+ final boolean isInFullScreenBookMode = deviceStateQuery
+ .isDisplayFullScreenAndSeparatingHinge()
+ && mAppCompatConfiguration.getIsAutomaticReachabilityInBookModeEnabled();
+ final int letterboxPositionForHorizontalReachability = mAppCompatConfiguration
+ .getLetterboxPositionForHorizontalReachability(isInFullScreenBookMode);
+ if (letterboxInnerFrame.left > x) {
+ // Moving to the next stop on the left side of the app window: right > center > left.
+ mAppCompatConfiguration.movePositionForHorizontalReachabilityToNextLeftStop(
+ isInFullScreenBookMode);
+ int letterboxPositionChangeForLog =
+ letterboxPositionForHorizontalReachability
+ == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER
+ ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_LEFT
+ : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__RIGHT_TO_CENTER;
+ logLetterboxPositionChange(letterboxPositionChangeForLog);
+ reachabilityOverrides.setDoubleTapEvent();
+ } else if (letterboxInnerFrame.right < x) {
+ // Moving to the next stop on the right side of the app window: left > center > right.
+ mAppCompatConfiguration.movePositionForHorizontalReachabilityToNextRightStop(
+ isInFullScreenBookMode);
+ final int letterboxPositionChangeForLog =
+ letterboxPositionForHorizontalReachability
+ == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER
+ ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_RIGHT
+ : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__LEFT_TO_CENTER;
+ logLetterboxPositionChange(letterboxPositionChangeForLog);
+ reachabilityOverrides.setDoubleTapEvent();
+ }
+ // TODO(197549949): Add animation for transition.
+ mActivityRecord.recomputeConfiguration();
+ }
+
+ @VisibleForTesting
+ void handleVerticalDoubleTap(int y, @NonNull Supplier<Rect> innerFrameSupplier) {
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides();
+ if (!reachabilityOverrides.isVerticalReachabilityEnabled()
+ || mActivityRecord.isInTransition()) {
+ return;
+ }
+ final Rect letterboxInnerFrame = innerFrameSupplier.get();
+ if (letterboxInnerFrame.top <= y && letterboxInnerFrame.bottom >= y) {
+ // Only react to clicks at the top and bottom of the letterboxed app window.
+ return;
+ }
+ final AppCompatDeviceStateQuery deviceStateQuery = mActivityRecord.mAppCompatController
+ .getAppCompatDeviceStateQuery();
+ final boolean isInFullScreenTabletopMode = deviceStateQuery
+ .isDisplayFullScreenAndSeparatingHinge();
+ final int letterboxPositionForVerticalReachability = mAppCompatConfiguration
+ .getLetterboxPositionForVerticalReachability(isInFullScreenTabletopMode);
+ if (letterboxInnerFrame.top > y) {
+ // Moving to the next stop on the top side of the app window: bottom > center > top.
+ mAppCompatConfiguration.movePositionForVerticalReachabilityToNextTopStop(
+ isInFullScreenTabletopMode);
+ final int letterboxPositionChangeForLog =
+ letterboxPositionForVerticalReachability
+ == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER
+ ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_TOP
+ : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__BOTTOM_TO_CENTER;
+ logLetterboxPositionChange(letterboxPositionChangeForLog);
+ reachabilityOverrides.setDoubleTapEvent();
+ } else if (letterboxInnerFrame.bottom < y) {
+ // Moving to the next stop on the bottom side of the app window: top > center > bottom.
+ mAppCompatConfiguration.movePositionForVerticalReachabilityToNextBottomStop(
+ isInFullScreenTabletopMode);
+ final int letterboxPositionChangeForLog =
+ letterboxPositionForVerticalReachability
+ == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER
+ ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_BOTTOM
+ : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__TOP_TO_CENTER;
+ logLetterboxPositionChange(letterboxPositionChangeForLog);
+ reachabilityOverrides.setDoubleTapEvent();
+ }
+ // TODO(197549949): Add animation for transition.
+ mActivityRecord.recomputeConfiguration();
+ }
+
+ /**
+ * Logs letterbox position changes via {@link ActivityMetricsLogger#logLetterboxPositionChange}.
+ */
+ private void logLetterboxPositionChange(int letterboxPositionChangeForLog) {
+ mActivityRecord.mTaskSupervisor.getActivityMetricsLogger()
+ .logLetterboxPositionChange(mActivityRecord, letterboxPositionChangeForLog);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/AppCompatUtils.java b/services/core/java/com/android/server/wm/AppCompatUtils.java
index a4cb389f118c..8c5193ef4a52 100644
--- a/services/core/java/com/android/server/wm/AppCompatUtils.java
+++ b/services/core/java/com/android/server/wm/AppCompatUtils.java
@@ -98,11 +98,11 @@ class AppCompatUtils {
appCompatTaskInfo.topActivityLetterboxHeight = TaskInfo.PROPERTY_VALUE_UNSET;
appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode =
CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_NONE;
-
if (top == null) {
return;
}
-
+ final AppCompatReachabilityOverrides reachabilityOverrides = top.mAppCompatController
+ .getAppCompatReachabilityOverrides();
final boolean isTopActivityResumed = top.getOrganizedTask() == task && top.isState(RESUMED);
final boolean isTopActivityVisible = top.getOrganizedTask() == task && top.isVisible();
// Whether the direct top activity is in size compat mode.
@@ -123,30 +123,27 @@ class AppCompatUtils {
appCompatTaskInfo.isSystemFullscreenOverrideEnabled = top.mAppCompatController
.getAppCompatAspectRatioOverrides().isSystemOverrideToFullscreenEnabled();
- appCompatTaskInfo.isFromLetterboxDoubleTap = top.mLetterboxUiController.isFromDoubleTap();
+ appCompatTaskInfo.isFromLetterboxDoubleTap = reachabilityOverrides.isFromDoubleTap();
appCompatTaskInfo.topActivityLetterboxWidth = top.getBounds().width();
appCompatTaskInfo.topActivityLetterboxHeight = top.getBounds().height();
-
// We need to consider if letterboxed or pillarboxed.
// TODO(b/336807329) Encapsulate reachability logic
- appCompatTaskInfo.isLetterboxDoubleTapEnabled = top.mLetterboxUiController
+ appCompatTaskInfo.isLetterboxDoubleTapEnabled = reachabilityOverrides
.isLetterboxDoubleTapEducationEnabled();
if (appCompatTaskInfo.isLetterboxDoubleTapEnabled) {
if (appCompatTaskInfo.isTopActivityPillarboxed()) {
- if (top.mLetterboxUiController.allowHorizontalReachabilityForThinLetterbox()) {
+ if (reachabilityOverrides.allowHorizontalReachabilityForThinLetterbox()) {
// Pillarboxed.
appCompatTaskInfo.topActivityLetterboxHorizontalPosition =
- top.mLetterboxUiController
- .getLetterboxPositionForHorizontalReachability();
+ reachabilityOverrides.getLetterboxPositionForHorizontalReachability();
} else {
appCompatTaskInfo.isLetterboxDoubleTapEnabled = false;
}
} else {
- if (top.mLetterboxUiController.allowVerticalReachabilityForThinLetterbox()) {
+ if (reachabilityOverrides.allowVerticalReachabilityForThinLetterbox()) {
// Letterboxed.
appCompatTaskInfo.topActivityLetterboxVerticalPosition =
- top.mLetterboxUiController
- .getLetterboxPositionForVerticalReachability();
+ reachabilityOverrides.getLetterboxPositionForVerticalReachability();
} else {
appCompatTaskInfo.isLetterboxDoubleTapEnabled = false;
}
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 291eab1b2d94..eb8a637285fb 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -16,37 +16,16 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__LEFT;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__RIGHT;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__TOP;
-import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__BOTTOM_TO_CENTER;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_BOTTOM;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_LEFT;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_RIGHT;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_TOP;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__LEFT_TO_CENTER;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__RIGHT_TO_CENTER;
-import static com.android.internal.util.FrameworkStatsLog.LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__TOP_TO_CENTER;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_WALLPAPER;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
import static com.android.server.wm.AppCompatConfiguration.letterboxBackgroundTypeToString;
import android.annotation.NonNull;
@@ -68,7 +47,6 @@ import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.wm.AppCompatConfiguration.LetterboxBackgroundType;
-import com.android.window.flags.Flags;
import java.io.PrintWriter;
@@ -92,8 +70,6 @@ final class LetterboxUiController {
private boolean mLastShouldShowLetterboxUi;
- private boolean mDoubleTapEvent;
-
LetterboxUiController(WindowManagerService wmService, ActivityRecord activityRecord) {
mAppCompatConfiguration = wmService.mAppCompatConfiguration;
// Given activityRecord may not be fully constructed since LetterboxUiController
@@ -231,7 +207,8 @@ final class LetterboxUiController {
.getTransparentPolicy().isRunning()
? mActivityRecord.getBounds() : w.getFrame();
mLetterbox.layout(spaceToFill, innerFrame, mTmpPoint);
- if (mDoubleTapEvent) {
+ if (mActivityRecord.mAppCompatController
+ .getAppCompatReachabilityOverrides().isDoubleTapEvent()) {
// We need to notify Shell that letterbox position has changed.
mActivityRecord.getTask().dispatchTaskInfoChangedIfNeeded(true /* force */);
}
@@ -240,12 +217,6 @@ final class LetterboxUiController {
}
}
- boolean isFromDoubleTap() {
- final boolean isFromDoubleTap = mDoubleTapEvent;
- mDoubleTapEvent = false;
- return isFromDoubleTap;
- }
-
SurfaceControl getLetterboxParentSurface() {
if (mActivityRecord.isInLetterboxAnimation()) {
return mActivityRecord.getTask().getSurfaceControl();
@@ -272,309 +243,35 @@ 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. If display is still in transition e.g. unfolding, don't return true
- // for HALF_FOLDED state or app will flicker.
- boolean isDisplayFullScreenAndInPosture(boolean isTabletop) {
- Task task = mActivityRecord.getTask();
- return mActivityRecord.mDisplayContent != null && task != null
- && mActivityRecord.mDisplayContent.getDisplayRotation().isDeviceInPosture(
- DeviceStateController.DeviceState.HALF_FOLDED, isTabletop)
- && !mActivityRecord.mDisplayContent.inTransition()
- && task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
+ float getHorizontalPositionMultiplier(@NonNull Configuration parentConfiguration) {
+ return mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides()
+ .getHorizontalPositionMultiplier(parentConfiguration);
}
- // 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 bookModeEnabled = isFullScreenAndBookModeEnabled();
- return isHorizontalReachabilityEnabled(parentConfiguration)
- // Using the last global dynamic position to avoid "jumps" when moving
- // between apps or activities.
- ? mAppCompatConfiguration.getHorizontalMultiplierForReachability(bookModeEnabled)
- : mAppCompatConfiguration.getLetterboxHorizontalPositionMultiplier(bookModeEnabled);
- }
-
- private boolean isFullScreenAndBookModeEnabled() {
- return isDisplayFullScreenAndInPosture(/* isTabletop */ false)
- && mAppCompatConfiguration.getIsAutomaticReachabilityInBookModeEnabled();
- }
-
- float getVerticalPositionMultiplier(Configuration parentConfiguration) {
- // Don't check resolved configuration because it may not be updated yet during
- // configuration change.
- boolean tabletopMode = isDisplayFullScreenAndInPosture(/* isTabletop */ true);
- return isVerticalReachabilityEnabled(parentConfiguration)
- // Using the last global dynamic position to avoid "jumps" when moving
- // between apps or activities.
- ? mAppCompatConfiguration.getVerticalMultiplierForReachability(tabletopMode)
- : mAppCompatConfiguration.getLetterboxVerticalPositionMultiplier(tabletopMode);
+ float getVerticalPositionMultiplier(@NonNull Configuration parentConfiguration) {
+ return mActivityRecord.mAppCompatController.getAppCompatReachabilityOverrides()
+ .getVerticalPositionMultiplier(parentConfiguration);
}
boolean isLetterboxEducationEnabled() {
return mAppCompatConfiguration.getIsEducationEnabled();
}
- /**
- * @return {@value true} if the resulting app is letterboxed in a way defined as thin.
- */
- boolean isVerticalThinLetterboxed() {
- final int thinHeight = mAppCompatConfiguration.getThinLetterboxHeightPx();
- if (thinHeight < 0) {
- return false;
- }
- final Task task = mActivityRecord.getTask();
- if (task == null) {
- return false;
- }
- final int padding = Math.abs(
- task.getBounds().height() - mActivityRecord.getBounds().height()) / 2;
- return padding <= thinHeight;
- }
-
- /**
- * @return {@value true} if the resulting app is pillarboxed in a way defined as thin.
- */
- boolean isHorizontalThinLetterboxed() {
- final int thinWidth = mAppCompatConfiguration.getThinLetterboxWidthPx();
- if (thinWidth < 0) {
- return false;
- }
- final Task task = mActivityRecord.getTask();
- if (task == null) {
- return false;
- }
- final int padding = Math.abs(
- task.getBounds().width() - mActivityRecord.getBounds().width()) / 2;
- return padding <= thinWidth;
- }
-
-
- /**
- * @return {@value true} if the vertical reachability should be allowed in case of
- * thin letteboxing
- */
- boolean allowVerticalReachabilityForThinLetterbox() {
- if (!Flags.disableThinLetterboxingPolicy()) {
- return true;
- }
- // When the flag is enabled we allow vertical reachability only if the
- // app is not thin letterboxed vertically.
- return !isVerticalThinLetterboxed();
- }
-
- /**
- * @return {@value true} if the vertical reachability should be enabled in case of
- * thin letteboxing
- */
- boolean allowHorizontalReachabilityForThinLetterbox() {
- if (!Flags.disableThinLetterboxingPolicy()) {
- return true;
- }
- // When the flag is enabled we allow horizontal reachability only if the
- // app is not thin pillarboxed.
- return !isHorizontalThinLetterboxed();
- }
-
- boolean shouldOverrideMinAspectRatio() {
- return mActivityRecord.mAppCompatController.getAppCompatAspectRatioOverrides()
- .shouldOverrideMinAspectRatio();
- }
-
- @AppCompatConfiguration.LetterboxVerticalReachabilityPosition
- int getLetterboxPositionForVerticalReachability() {
- final boolean isInFullScreenTabletopMode = isDisplayFullScreenAndSeparatingHinge();
- return mAppCompatConfiguration.getLetterboxPositionForVerticalReachability(
- isInFullScreenTabletopMode);
- }
-
- @AppCompatConfiguration.LetterboxHorizontalReachabilityPosition
- int getLetterboxPositionForHorizontalReachability() {
- final boolean isInFullScreenBookMode = isFullScreenAndBookModeEnabled();
- return mAppCompatConfiguration.getLetterboxPositionForHorizontalReachability(
- isInFullScreenBookMode);
- }
-
@VisibleForTesting
void handleHorizontalDoubleTap(int x) {
- if (!isHorizontalReachabilityEnabled() || mActivityRecord.isInTransition()) {
- return;
- }
-
- if (mLetterbox.getInnerFrame().left <= x && mLetterbox.getInnerFrame().right >= x) {
- // Only react to clicks at the sides of the letterboxed app window.
- return;
- }
-
- boolean isInFullScreenBookMode = isDisplayFullScreenAndSeparatingHinge()
- && mAppCompatConfiguration.getIsAutomaticReachabilityInBookModeEnabled();
- int letterboxPositionForHorizontalReachability = mAppCompatConfiguration
- .getLetterboxPositionForHorizontalReachability(isInFullScreenBookMode);
- if (mLetterbox.getInnerFrame().left > x) {
- // Moving to the next stop on the left side of the app window: right > center > left.
- mAppCompatConfiguration.movePositionForHorizontalReachabilityToNextLeftStop(
- isInFullScreenBookMode);
- int changeToLog =
- letterboxPositionForHorizontalReachability
- == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER
- ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_LEFT
- : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__RIGHT_TO_CENTER;
- logLetterboxPositionChange(changeToLog);
- mDoubleTapEvent = true;
- } else if (mLetterbox.getInnerFrame().right < x) {
- // Moving to the next stop on the right side of the app window: left > center > right.
- mAppCompatConfiguration.movePositionForHorizontalReachabilityToNextRightStop(
- isInFullScreenBookMode);
- int changeToLog =
- letterboxPositionForHorizontalReachability
- == LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER
- ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_RIGHT
- : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__LEFT_TO_CENTER;
- logLetterboxPositionChange(changeToLog);
- mDoubleTapEvent = true;
- }
- // TODO(197549949): Add animation for transition.
- mActivityRecord.recomputeConfiguration();
+ mActivityRecord.mAppCompatController.getAppCompatReachabilityPolicy()
+ .handleHorizontalDoubleTap(x, mLetterbox::getInnerFrame);
}
@VisibleForTesting
void handleVerticalDoubleTap(int y) {
- if (!isVerticalReachabilityEnabled() || mActivityRecord.isInTransition()) {
- return;
- }
-
- if (mLetterbox.getInnerFrame().top <= y && mLetterbox.getInnerFrame().bottom >= y) {
- // Only react to clicks at the top and bottom of the letterboxed app window.
- return;
- }
- boolean isInFullScreenTabletopMode = isDisplayFullScreenAndSeparatingHinge();
- int letterboxPositionForVerticalReachability = mAppCompatConfiguration
- .getLetterboxPositionForVerticalReachability(isInFullScreenTabletopMode);
- if (mLetterbox.getInnerFrame().top > y) {
- // Moving to the next stop on the top side of the app window: bottom > center > top.
- mAppCompatConfiguration.movePositionForVerticalReachabilityToNextTopStop(
- isInFullScreenTabletopMode);
- int changeToLog =
- letterboxPositionForVerticalReachability
- == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER
- ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_TOP
- : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__BOTTOM_TO_CENTER;
- logLetterboxPositionChange(changeToLog);
- mDoubleTapEvent = true;
- } else if (mLetterbox.getInnerFrame().bottom < y) {
- // Moving to the next stop on the bottom side of the app window: top > center > bottom.
- mAppCompatConfiguration.movePositionForVerticalReachabilityToNextBottomStop(
- isInFullScreenTabletopMode);
- int changeToLog =
- letterboxPositionForVerticalReachability
- == LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER
- ? LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__CENTER_TO_BOTTOM
- : LETTERBOX_POSITION_CHANGED__POSITION_CHANGE__TOP_TO_CENTER;
- logLetterboxPositionChange(changeToLog);
- mDoubleTapEvent = true;
- }
- // TODO(197549949): Add animation for transition.
- mActivityRecord.recomputeConfiguration();
- }
-
- /**
- * Whether horizontal reachability is enabled for an activity in the current configuration.
- *
- * <p>Conditions that needs to be met:
- * <ul>
- * <li>Windowing mode is fullscreen.
- * <li>Horizontal Reachability is enabled.
- * <li>First top opaque activity fills parent vertically, but not horizontally.
- * </ul>
- */
- private boolean isHorizontalReachabilityEnabled(Configuration parentConfiguration) {
- if (!allowHorizontalReachabilityForThinLetterbox()) {
- return false;
- }
- final Rect parentAppBoundsOverride = mActivityRecord.getParentAppBoundsOverride();
- final Rect parentAppBounds = parentAppBoundsOverride != null
- ? parentAppBoundsOverride : parentConfiguration.windowConfiguration.getAppBounds();
- // Use screen resolved bounds which uses resolved bounds or size compat bounds
- // as activity bounds can sometimes be empty
- final Rect opaqueActivityBounds = mActivityRecord.mAppCompatController
- .getTransparentPolicy().getFirstOpaqueActivity()
- .map(ActivityRecord::getScreenResolvedBounds)
- .orElse(mActivityRecord.getScreenResolvedBounds());
- return mAppCompatConfiguration.getIsHorizontalReachabilityEnabled()
- && parentConfiguration.windowConfiguration.getWindowingMode()
- == WINDOWING_MODE_FULLSCREEN
- // Check whether the activity fills the parent vertically.
- && parentAppBounds.height() <= opaqueActivityBounds.height()
- && parentAppBounds.width() > opaqueActivityBounds.width();
- }
-
- @VisibleForTesting
- boolean isHorizontalReachabilityEnabled() {
- return isHorizontalReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
- }
-
- boolean isLetterboxDoubleTapEducationEnabled() {
- return isHorizontalReachabilityEnabled() || isVerticalReachabilityEnabled();
- }
-
- // TODO(b/346264992): Remove after AppCompatController refactoring
- private AppCompatOverrides getAppCompatOverrides() {
- return mActivityRecord.mAppCompatController.getAppCompatOverrides();
- }
-
- /**
- * Whether vertical reachability is enabled for an activity in the current configuration.
- *
- * <p>Conditions that needs to be met:
- * <ul>
- * <li>Windowing mode is fullscreen.
- * <li>Vertical Reachability is enabled.
- * <li>First top opaque activity fills parent horizontally but not vertically.
- * </ul>
- */
- private boolean isVerticalReachabilityEnabled(Configuration parentConfiguration) {
- if (!allowVerticalReachabilityForThinLetterbox()) {
- return false;
- }
- final Rect parentAppBoundsOverride = mActivityRecord.getParentAppBoundsOverride();
- final Rect parentAppBounds = parentAppBoundsOverride != null
- ? parentAppBoundsOverride : parentConfiguration.windowConfiguration.getAppBounds();
- // Use screen resolved bounds which uses resolved bounds or size compat bounds
- // as activity bounds can sometimes be empty.
- final Rect opaqueActivityBounds = mActivityRecord.mAppCompatController
- .getTransparentPolicy().getFirstOpaqueActivity()
- .map(ActivityRecord::getScreenResolvedBounds)
- .orElse(mActivityRecord.getScreenResolvedBounds());
- return mAppCompatConfiguration.getIsVerticalReachabilityEnabled()
- && parentConfiguration.windowConfiguration.getWindowingMode()
- == WINDOWING_MODE_FULLSCREEN
- // Check whether the activity fills the parent horizontally.
- && parentAppBounds.width() <= opaqueActivityBounds.width()
- && parentAppBounds.height() > opaqueActivityBounds.height();
- }
-
- @VisibleForTesting
- boolean isVerticalReachabilityEnabled() {
- return isVerticalReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
+ mActivityRecord.mAppCompatController.getAppCompatReachabilityPolicy()
+ .handleVerticalDoubleTap(y, mLetterbox::getInnerFrame);
}
@VisibleForTesting
boolean shouldShowLetterboxUi(WindowState mainWindow) {
- if (getAppCompatOverrides().getAppCompatOrientationOverrides()
+ if (mActivityRecord.mAppCompatController.getAppCompatOrientationOverrides()
.getIsRelaunchingAfterRequestedOrientationChanged()) {
return mLastShouldShowLetterboxUi;
}
@@ -818,8 +515,10 @@ final class LetterboxUiController {
if (!shouldShowLetterboxUi) {
return;
}
- pw.println(prefix + " isVerticalThinLetterboxed=" + isVerticalThinLetterboxed());
- pw.println(prefix + " isHorizontalThinLetterboxed=" + isHorizontalThinLetterboxed());
+ pw.println(prefix + " isVerticalThinLetterboxed=" + mActivityRecord.mAppCompatController
+ .getAppCompatReachabilityOverrides().isVerticalThinLetterboxed());
+ pw.println(prefix + " isHorizontalThinLetterboxed=" + mActivityRecord.mAppCompatController
+ .getAppCompatReachabilityOverrides().isHorizontalThinLetterboxed());
pw.println(prefix + " letterboxBackgroundColor=" + Integer.toHexString(
getLetterboxBackgroundColor().toArgb()));
pw.println(prefix + " letterboxBackgroundType="
@@ -836,10 +535,12 @@ final class LetterboxUiController {
pw.println(prefix + " letterboxBackgroundWallpaperBlurRadius="
+ getLetterboxWallpaperBlurRadiusPx());
}
-
+ final AppCompatReachabilityOverrides reachabilityOverrides = mActivityRecord
+ .mAppCompatController.getAppCompatReachabilityOverrides();
pw.println(prefix + " isHorizontalReachabilityEnabled="
- + isHorizontalReachabilityEnabled());
- pw.println(prefix + " isVerticalReachabilityEnabled=" + isVerticalReachabilityEnabled());
+ + reachabilityOverrides.isHorizontalReachabilityEnabled());
+ pw.println(prefix + " isVerticalReachabilityEnabled="
+ + reachabilityOverrides.isVerticalReachabilityEnabled());
pw.println(prefix + " letterboxHorizontalPositionMultiplier="
+ getHorizontalPositionMultiplier(mActivityRecord.getParent().getConfiguration()));
pw.println(prefix + " letterboxVerticalPositionMultiplier="
@@ -883,64 +584,6 @@ final class LetterboxUiController {
return "UNKNOWN_REASON";
}
- private int letterboxHorizontalReachabilityPositionToLetterboxPosition(
- @AppCompatConfiguration.LetterboxHorizontalReachabilityPosition int position) {
- switch (position) {
- case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__LEFT;
- case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
- case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__RIGHT;
- default:
- throw new AssertionError(
- "Unexpected letterbox horizontal reachability position type: "
- + position);
- }
- }
-
- private int letterboxVerticalReachabilityPositionToLetterboxPosition(
- @AppCompatConfiguration.LetterboxVerticalReachabilityPosition int position) {
- switch (position) {
- case LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__TOP;
- case LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__CENTER;
- case LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM:
- return APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
- default:
- throw new AssertionError(
- "Unexpected letterbox vertical reachability position type: "
- + position);
- }
- }
-
- int getLetterboxPositionForLogging() {
- int positionToLog = APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__UNKNOWN_POSITION;
- if (isHorizontalReachabilityEnabled()) {
- int letterboxPositionForHorizontalReachability = mAppCompatConfiguration
- .getLetterboxPositionForHorizontalReachability(
- isDisplayFullScreenAndInPosture(/* isTabletop */ false));
- positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPosition(
- letterboxPositionForHorizontalReachability);
- } else if (isVerticalReachabilityEnabled()) {
- int letterboxPositionForVerticalReachability = mAppCompatConfiguration
- .getLetterboxPositionForVerticalReachability(
- isDisplayFullScreenAndInPosture(/* isTabletop */ true));
- positionToLog = letterboxVerticalReachabilityPositionToLetterboxPosition(
- letterboxPositionForVerticalReachability);
- }
- return positionToLog;
- }
-
- /**
- * Logs letterbox position changes via {@link ActivityMetricsLogger#logLetterboxPositionChange}.
- */
- private void logLetterboxPositionChange(int letterboxPositionChange) {
- mActivityRecord.mTaskSupervisor.getActivityMetricsLogger()
- .logLetterboxPositionChange(mActivityRecord, letterboxPositionChange);
- }
-
@Nullable
LetterboxDetails getLetterboxDetails() {
final WindowState w = mActivityRecord.findMainWindow();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7ada4c7f9c09..d3df5fdcc447 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3389,7 +3389,6 @@ class Task extends TaskFragment {
info.isTopActivityTransparent = top != null && !top.fillsParent();
info.isTopActivityStyleFloating = top != null && top.isStyleFloating();
info.lastNonFullscreenBounds = topTask.mLastNonFullscreenBounds;
-
AppCompatUtils.fillAppCompatTaskInfo(this, info, top);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index 61a6f316244c..33df5d896f7f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -300,7 +300,9 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
// Vertical thin letterbox disabled
doReturn(-1).when(mActivity.mWmService.mAppCompatConfiguration)
.getThinLetterboxHeightPx();
- assertFalse(mController.isVerticalThinLetterboxed());
+ final AppCompatReachabilityOverrides reachabilityOverrides = mActivity.mAppCompatController
+ .getAppCompatReachabilityOverrides();
+ assertFalse(reachabilityOverrides.isVerticalThinLetterboxed());
// Define a Task 100x100
final Task task = mock(Task.class);
doReturn(new Rect(0, 0, 100, 100)).when(task).getBounds();
@@ -309,21 +311,21 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
// Vertical thin letterbox disabled without Task
doReturn(null).when(mActivity).getTask();
- assertFalse(mController.isVerticalThinLetterboxed());
+ assertFalse(reachabilityOverrides.isVerticalThinLetterboxed());
// Assign a Task for the Activity
doReturn(task).when(mActivity).getTask();
// (task.width() - act.width()) / 2 = 5 < 10
doReturn(new Rect(5, 5, 95, 95)).when(mActivity).getBounds();
- assertTrue(mController.isVerticalThinLetterboxed());
+ assertTrue(reachabilityOverrides.isVerticalThinLetterboxed());
// (task.width() - act.width()) / 2 = 10 = 10
doReturn(new Rect(10, 10, 90, 90)).when(mActivity).getBounds();
- assertTrue(mController.isVerticalThinLetterboxed());
+ assertTrue(reachabilityOverrides.isVerticalThinLetterboxed());
// (task.width() - act.width()) / 2 = 11 > 10
doReturn(new Rect(11, 11, 89, 89)).when(mActivity).getBounds();
- assertFalse(mController.isVerticalThinLetterboxed());
+ assertFalse(reachabilityOverrides.isVerticalThinLetterboxed());
}
@Test
@@ -331,7 +333,9 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
// Horizontal thin letterbox disabled
doReturn(-1).when(mActivity.mWmService.mAppCompatConfiguration)
.getThinLetterboxWidthPx();
- assertFalse(mController.isHorizontalThinLetterboxed());
+ final AppCompatReachabilityOverrides reachabilityOverrides = mActivity.mAppCompatController
+ .getAppCompatReachabilityOverrides();
+ assertFalse(reachabilityOverrides.isHorizontalThinLetterboxed());
// Define a Task 100x100
final Task task = mock(Task.class);
doReturn(new Rect(0, 0, 100, 100)).when(task).getBounds();
@@ -340,51 +344,55 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
// Vertical thin letterbox disabled without Task
doReturn(null).when(mActivity).getTask();
- assertFalse(mController.isHorizontalThinLetterboxed());
+ assertFalse(reachabilityOverrides.isHorizontalThinLetterboxed());
// Assign a Task for the Activity
doReturn(task).when(mActivity).getTask();
// (task.height() - act.height()) / 2 = 5 < 10
doReturn(new Rect(5, 5, 95, 95)).when(mActivity).getBounds();
- assertTrue(mController.isHorizontalThinLetterboxed());
+ assertTrue(reachabilityOverrides.isHorizontalThinLetterboxed());
// (task.height() - act.height()) / 2 = 10 = 10
doReturn(new Rect(10, 10, 90, 90)).when(mActivity).getBounds();
- assertTrue(mController.isHorizontalThinLetterboxed());
+ assertTrue(reachabilityOverrides.isHorizontalThinLetterboxed());
// (task.height() - act.height()) / 2 = 11 > 10
doReturn(new Rect(11, 11, 89, 89)).when(mActivity).getBounds();
- assertFalse(mController.isHorizontalThinLetterboxed());
+ assertFalse(reachabilityOverrides.isHorizontalThinLetterboxed());
}
@Test
@EnableFlags(Flags.FLAG_DISABLE_THIN_LETTERBOXING_POLICY)
public void testAllowReachabilityForThinLetterboxWithFlagEnabled() {
- spyOn(mController);
- doReturn(true).when(mController).isVerticalThinLetterboxed();
- assertFalse(mController.allowVerticalReachabilityForThinLetterbox());
- doReturn(true).when(mController).isHorizontalThinLetterboxed();
- assertFalse(mController.allowHorizontalReachabilityForThinLetterbox());
-
- doReturn(false).when(mController).isVerticalThinLetterboxed();
- assertTrue(mController.allowVerticalReachabilityForThinLetterbox());
- doReturn(false).when(mController).isHorizontalThinLetterboxed();
- assertTrue(mController.allowHorizontalReachabilityForThinLetterbox());
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivity.mAppCompatController.getAppCompatReachabilityOverrides();
+ spyOn(reachabilityOverrides);
+ doReturn(true).when(reachabilityOverrides).isVerticalThinLetterboxed();
+ assertFalse(reachabilityOverrides.allowVerticalReachabilityForThinLetterbox());
+ doReturn(true).when(reachabilityOverrides).isHorizontalThinLetterboxed();
+ assertFalse(reachabilityOverrides.allowHorizontalReachabilityForThinLetterbox());
+
+ doReturn(false).when(reachabilityOverrides).isVerticalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowVerticalReachabilityForThinLetterbox());
+ doReturn(false).when(reachabilityOverrides).isHorizontalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowHorizontalReachabilityForThinLetterbox());
}
@Test
@DisableFlags(Flags.FLAG_DISABLE_THIN_LETTERBOXING_POLICY)
public void testAllowReachabilityForThinLetterboxWithFlagDisabled() {
- spyOn(mController);
- doReturn(true).when(mController).isVerticalThinLetterboxed();
- assertTrue(mController.allowVerticalReachabilityForThinLetterbox());
- doReturn(true).when(mController).isHorizontalThinLetterboxed();
- assertTrue(mController.allowHorizontalReachabilityForThinLetterbox());
-
- doReturn(false).when(mController).isVerticalThinLetterboxed();
- assertTrue(mController.allowVerticalReachabilityForThinLetterbox());
- doReturn(false).when(mController).isHorizontalThinLetterboxed();
- assertTrue(mController.allowHorizontalReachabilityForThinLetterbox());
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivity.mAppCompatController.getAppCompatReachabilityOverrides();
+ spyOn(reachabilityOverrides);
+ doReturn(true).when(reachabilityOverrides).isVerticalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowVerticalReachabilityForThinLetterbox());
+ doReturn(true).when(reachabilityOverrides).isHorizontalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowHorizontalReachabilityForThinLetterbox());
+
+ doReturn(false).when(reachabilityOverrides).isVerticalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowVerticalReachabilityForThinLetterbox());
+ doReturn(false).when(reachabilityOverrides).isHorizontalThinLetterboxed();
+ assertTrue(reachabilityOverrides.allowHorizontalReachabilityForThinLetterbox());
}
@Test
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 ed93a8c6ecff..7dc3b07b6ce2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -3431,9 +3431,10 @@ public class SizeCompatTests extends WindowTestsBase {
mActivity.getWindowConfiguration().setBounds(null);
setUpAllowThinLetterboxed(/* thinLetterboxAllowed */ false);
-
- assertFalse(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
- assertFalse(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivity.mAppCompatController.getAppCompatReachabilityOverrides();
+ assertFalse(reachabilityOverrides.isVerticalReachabilityEnabled());
+ assertFalse(reachabilityOverrides.isHorizontalReachabilityEnabled());
}
@Test
@@ -3456,7 +3457,8 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
// Horizontal reachability is disabled because the app is in split screen.
- assertFalse(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isHorizontalReachabilityEnabled());
}
@Test
@@ -3479,7 +3481,8 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
// Vertical reachability is disabled because the app is in split screen.
- assertFalse(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isVerticalReachabilityEnabled());
}
@Test
@@ -3501,7 +3504,8 @@ public class SizeCompatTests extends WindowTestsBase {
// Vertical reachability is disabled because the app does not match parent width
assertNotEquals(mActivity.getScreenResolvedBounds().width(),
mActivity.mDisplayContent.getBounds().width());
- assertFalse(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isVerticalReachabilityEnabled());
}
@Test
@@ -3518,7 +3522,8 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(new Rect(0, 0, 0, 0), mActivity.getBounds());
// Vertical reachability is still enabled as resolved bounds is not empty
- assertTrue(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isVerticalReachabilityEnabled());
}
@Test
@@ -3535,7 +3540,8 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(new Rect(0, 0, 0, 0), mActivity.getBounds());
// Horizontal reachability is still enabled as resolved bounds is not empty
- assertTrue(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isHorizontalReachabilityEnabled());
}
@Test
@@ -3549,7 +3555,8 @@ public class SizeCompatTests extends WindowTestsBase {
prepareMinAspectRatio(mActivity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
SCREEN_ORIENTATION_PORTRAIT);
- assertTrue(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isHorizontalReachabilityEnabled());
}
@Test
@@ -3563,7 +3570,8 @@ public class SizeCompatTests extends WindowTestsBase {
prepareMinAspectRatio(mActivity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
SCREEN_ORIENTATION_LANDSCAPE);
- assertTrue(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isVerticalReachabilityEnabled());
}
@Test
@@ -3585,7 +3593,8 @@ public class SizeCompatTests extends WindowTestsBase {
// Horizontal reachability is disabled because the app does not match parent height
assertNotEquals(mActivity.getScreenResolvedBounds().height(),
mActivity.mDisplayContent.getBounds().height());
- assertFalse(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ assertFalse(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isHorizontalReachabilityEnabled());
}
@Test
@@ -3607,7 +3616,8 @@ public class SizeCompatTests extends WindowTestsBase {
// Horizontal reachability is enabled because the app matches parent height
assertEquals(mActivity.getScreenResolvedBounds().height(),
mActivity.mDisplayContent.getBounds().height());
- assertTrue(mActivity.mLetterboxUiController.isHorizontalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isHorizontalReachabilityEnabled());
}
@Test
@@ -3629,7 +3639,8 @@ public class SizeCompatTests extends WindowTestsBase {
// Vertical reachability is enabled because the app matches parent width
assertEquals(mActivity.getScreenResolvedBounds().width(),
mActivity.mDisplayContent.getBounds().width());
- assertTrue(mActivity.mLetterboxUiController.isVerticalReachabilityEnabled());
+ assertTrue(mActivity.mAppCompatController.getAppCompatReachabilityOverrides()
+ .isVerticalReachabilityEnabled());
}
@Test
@@ -4809,10 +4820,12 @@ public class SizeCompatTests extends WindowTestsBase {
}
private void setUpAllowThinLetterboxed(boolean thinLetterboxAllowed) {
- spyOn(mActivity.mLetterboxUiController);
- doReturn(thinLetterboxAllowed).when(mActivity.mLetterboxUiController)
+ final AppCompatReachabilityOverrides reachabilityOverrides =
+ mActivity.mAppCompatController.getAppCompatReachabilityOverrides();
+ spyOn(reachabilityOverrides);
+ doReturn(thinLetterboxAllowed).when(reachabilityOverrides)
.allowVerticalReachabilityForThinLetterbox();
- doReturn(thinLetterboxAllowed).when(mActivity.mLetterboxUiController)
+ doReturn(thinLetterboxAllowed).when(reachabilityOverrides)
.allowHorizontalReachabilityForThinLetterbox();
}