Loading services/core/java/com/android/server/wm/ActivityMetricsLogger.java +2 −1 Original line number Diff line number Diff line Loading @@ -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); Loading services/core/java/com/android/server/wm/ActivityRecord.java +6 −4 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. Loading @@ -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. Loading services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java +13 −14 Original line number Diff line number Diff line Loading @@ -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. */ Loading @@ -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( Loading Loading @@ -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 = Loading services/core/java/com/android/server/wm/AppCompatController.java +24 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 Loading Loading @@ -100,8 +107,24 @@ class AppCompatController { return null; } @NonNull AppCompatReachabilityPolicy getAppCompatReachabilityPolicy() { return mAppCompatReachabilityPolicy; } @NonNull AppCompatFocusOverrides getAppCompatFocusOverrides() { return mAppCompatOverrides.getAppCompatFocusOverrides(); } @NonNull AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() { return mAppCompatOverrides.getAppCompatReachabilityOverrides(); } @NonNull AppCompatDeviceStateQuery getAppCompatDeviceStateQuery() { return mAppCompatDeviceStateQuery; } } services/core/java/com/android/server/wm/AppCompatDeviceStateQuery.java 0 → 100644 +64 −0 Original line number Diff line number Diff line /* * 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; } } Loading
services/core/java/com/android/server/wm/ActivityMetricsLogger.java +2 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
services/core/java/com/android/server/wm/ActivityRecord.java +6 −4 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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. Loading @@ -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. Loading
services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java +13 −14 Original line number Diff line number Diff line Loading @@ -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. */ Loading @@ -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( Loading Loading @@ -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 = Loading
services/core/java/com/android/server/wm/AppCompatController.java +24 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 Loading Loading @@ -100,8 +107,24 @@ class AppCompatController { return null; } @NonNull AppCompatReachabilityPolicy getAppCompatReachabilityPolicy() { return mAppCompatReachabilityPolicy; } @NonNull AppCompatFocusOverrides getAppCompatFocusOverrides() { return mAppCompatOverrides.getAppCompatFocusOverrides(); } @NonNull AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() { return mAppCompatOverrides.getAppCompatReachabilityOverrides(); } @NonNull AppCompatDeviceStateQuery getAppCompatDeviceStateQuery() { return mAppCompatDeviceStateQuery; } }
services/core/java/com/android/server/wm/AppCompatDeviceStateQuery.java 0 → 100644 +64 −0 Original line number Diff line number Diff line /* * 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; } }