Loading core/java/android/app/AppCompatTaskInfo.java +20 −2 Original line number Diff line number Diff line Loading @@ -104,6 +104,8 @@ public class AppCompatTaskInfo implements Parcelable { public static final int FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE = FLAG_BASE << 9; /** Top activity flag for whether restart menu is shown due to display move. */ private static final int FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE = FLAG_BASE << 10; /** Top activity flag for whether activity opted out of edge to edge. */ public static final int FLAG_OPT_OUT_EDGE_TO_EDGE = FLAG_BASE << 11; @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = { Loading @@ -118,7 +120,8 @@ public class AppCompatTaskInfo implements Parcelable { FLAG_FULLSCREEN_OVERRIDE_SYSTEM, FLAG_FULLSCREEN_OVERRIDE_USER, FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE, FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE, FLAG_OPT_OUT_EDGE_TO_EDGE }) public @interface TopActivityFlag {} Loading @@ -132,7 +135,8 @@ public class AppCompatTaskInfo implements Parcelable { @TopActivityFlag private static final int FLAGS_ORGANIZER_INTERESTED = FLAG_IS_FROM_LETTERBOX_DOUBLE_TAP | FLAG_ELIGIBLE_FOR_USER_ASPECT_RATIO_BUTTON | FLAG_FULLSCREEN_OVERRIDE_SYSTEM | FLAG_FULLSCREEN_OVERRIDE_USER | FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE; | FLAG_FULLSCREEN_OVERRIDE_USER | FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE | FLAG_OPT_OUT_EDGE_TO_EDGE; @TopActivityFlag private static final int FLAGS_COMPAT_UI_INTERESTED = FLAGS_ORGANIZER_INTERESTED Loading Loading @@ -347,6 +351,20 @@ public class AppCompatTaskInfo implements Parcelable { setTopActivityFlag(FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE, enable); } /** * Sets the top activity flag for whether the activity has opted out of edge to edge. */ public void setOptOutEdgeToEdge(boolean enable) { setTopActivityFlag(FLAG_OPT_OUT_EDGE_TO_EDGE, enable); } /** * @return {@code true} if the top activity has opted out of edge to edge. */ public boolean hasOptOutEdgeToEdge() { return isTopActivityFlagEnabled(FLAG_OPT_OUT_EDGE_TO_EDGE); } /** Clear all top activity flags and set to false. */ public void clearTopActivityFlags() { mTopActivityFlags = FLAG_UNDEFINED; Loading core/java/com/android/internal/policy/DesktopModeCompatUtils.java 0 → 100644 +60 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.internal.policy; import static android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED; import static android.content.pm.ActivityInfo.OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS; import android.annotation.NonNull; import android.content.pm.ActivityInfo; import android.window.DesktopModeFlags; /** * Utility functions for app compat in desktop windowing used by both window manager and System UI. * @hide */ public final class DesktopModeCompatUtils { /** * Whether the caption insets should be excluded from configuration for system to handle. * The caller should ensure the activity is in or entering desktop view. * * <p> The treatment is enabled when all the of the following is true: * <li> Any flags to forcibly consume caption insets are enabled. * <li> Top activity have configuration coupled with insets. * <li> Task is not resizeable or per-app override * {@link ActivityInfo#OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS} is enabled. */ public static boolean shouldExcludeCaptionFromAppBounds(@NonNull ActivityInfo info, boolean isResizeable, boolean optOutEdgeToEdge) { return DesktopModeFlags.EXCLUDE_CAPTION_FROM_APP_BOUNDS.isTrue() && isAnyForceConsumptionFlagsEnabled() && !isConfigurationDecoupled(info, optOutEdgeToEdge) && (!isResizeable || info.isChangeEnabled(OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS)); } private static boolean isConfigurationDecoupled(@NonNull ActivityInfo info, boolean optOutEdgeToEdge) { return info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED) && !optOutEdgeToEdge; } private static boolean isAnyForceConsumptionFlagsEnabled() { return DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isTrue() || DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isTrue(); } } libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt +5 −27 Original line number Diff line number Diff line Loading @@ -19,13 +19,10 @@ package com.android.wm.shell.shared.desktopmode import android.Manifest.permission.SYSTEM_ALERT_WINDOW import android.app.TaskInfo import android.content.Context import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED import android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION import android.content.pm.ActivityInfo.OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS import android.content.pm.PackageManager import android.window.DesktopModeFlags import com.android.internal.R import com.android.internal.policy.DesktopModeCompatUtils /** * Class to decide whether to apply app compat policies in desktop mode. Loading Loading @@ -60,22 +57,11 @@ class DesktopModeCompatPolicy(private val context: Context) { hasFullscreenTransparentPermission(packageName))) && !isTopActivityNoDisplay) /** * Whether the caption insets should be excluded from configuration for system to handle. * * The treatment is enabled when all the of the following is true: * * Any flags to forcibly consume caption insets are enabled. * * Top activity have configuration coupled with insets. * * Task is not resizeable or [ActivityInfo.OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS] * is enabled. */ /** @see DesktopModeCompatUtils.shouldExcludeCaptionFromAppBounds */ fun shouldExcludeCaptionFromAppBounds(taskInfo: TaskInfo): Boolean = DesktopModeFlags.EXCLUDE_CAPTION_FROM_APP_BOUNDS.isTrue && isAnyForceConsumptionFlagsEnabled() && taskInfo.topActivityInfo?.let { isInsetsCoupledWithConfiguration(it) && (!taskInfo.isResizeable || it.isChangeEnabled( OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS )) taskInfo.topActivityInfo?.let { DesktopModeCompatUtils.shouldExcludeCaptionFromAppBounds(it, taskInfo.isResizeable, taskInfo.appCompatTaskInfo.hasOptOutEdgeToEdge()) } ?: false /** Loading Loading @@ -118,12 +104,4 @@ class DesktopModeCompatPolicy(private val context: Context) { */ private fun isPartOfDefaultHomePackageOrNoHomeAvailable(packageName: String?) = defaultHomePackage == null || (packageName != null && packageName == defaultHomePackage) private fun isAnyForceConsumptionFlagsEnabled(): Boolean = DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isTrue || DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isTrue private fun isInsetsCoupledWithConfiguration(info: ActivityInfo): Boolean = !(info.isChangeEnabled(OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION) || info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)) } services/core/java/com/android/server/wm/ActivityRecord.java +1 −1 Original line number Diff line number Diff line Loading @@ -625,7 +625,7 @@ final class ActivityRecord extends WindowToken { @VisibleForTesting final TaskFragment.ConfigOverrideHint mResolveConfigHint; private final boolean mOptOutEdgeToEdge; final boolean mOptOutEdgeToEdge; private static ConstrainDisplayApisConfig sConstrainDisplayApisConfig; Loading services/core/java/com/android/server/wm/AppCompatUtils.java +1 −0 Original line number Diff line number Diff line Loading @@ -216,6 +216,7 @@ final class AppCompatUtils { AppCompatCameraPolicy.getCameraCompatFreeformMode(top); appCompatTaskInfo.setHasMinAspectRatioOverride(top.mAppCompatController .getDesktopAspectRatioPolicy().hasMinAspectRatioOverride(task)); appCompatTaskInfo.setOptOutEdgeToEdge(top.mOptOutEdgeToEdge); } /** Loading Loading
core/java/android/app/AppCompatTaskInfo.java +20 −2 Original line number Diff line number Diff line Loading @@ -104,6 +104,8 @@ public class AppCompatTaskInfo implements Parcelable { public static final int FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE = FLAG_BASE << 9; /** Top activity flag for whether restart menu is shown due to display move. */ private static final int FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE = FLAG_BASE << 10; /** Top activity flag for whether activity opted out of edge to edge. */ public static final int FLAG_OPT_OUT_EDGE_TO_EDGE = FLAG_BASE << 11; @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = { Loading @@ -118,7 +120,8 @@ public class AppCompatTaskInfo implements Parcelable { FLAG_FULLSCREEN_OVERRIDE_SYSTEM, FLAG_FULLSCREEN_OVERRIDE_USER, FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE, FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE, FLAG_OPT_OUT_EDGE_TO_EDGE }) public @interface TopActivityFlag {} Loading @@ -132,7 +135,8 @@ public class AppCompatTaskInfo implements Parcelable { @TopActivityFlag private static final int FLAGS_ORGANIZER_INTERESTED = FLAG_IS_FROM_LETTERBOX_DOUBLE_TAP | FLAG_ELIGIBLE_FOR_USER_ASPECT_RATIO_BUTTON | FLAG_FULLSCREEN_OVERRIDE_SYSTEM | FLAG_FULLSCREEN_OVERRIDE_USER | FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE; | FLAG_FULLSCREEN_OVERRIDE_USER | FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE | FLAG_OPT_OUT_EDGE_TO_EDGE; @TopActivityFlag private static final int FLAGS_COMPAT_UI_INTERESTED = FLAGS_ORGANIZER_INTERESTED Loading Loading @@ -347,6 +351,20 @@ public class AppCompatTaskInfo implements Parcelable { setTopActivityFlag(FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE, enable); } /** * Sets the top activity flag for whether the activity has opted out of edge to edge. */ public void setOptOutEdgeToEdge(boolean enable) { setTopActivityFlag(FLAG_OPT_OUT_EDGE_TO_EDGE, enable); } /** * @return {@code true} if the top activity has opted out of edge to edge. */ public boolean hasOptOutEdgeToEdge() { return isTopActivityFlagEnabled(FLAG_OPT_OUT_EDGE_TO_EDGE); } /** Clear all top activity flags and set to false. */ public void clearTopActivityFlags() { mTopActivityFlags = FLAG_UNDEFINED; Loading
core/java/com/android/internal/policy/DesktopModeCompatUtils.java 0 → 100644 +60 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.internal.policy; import static android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED; import static android.content.pm.ActivityInfo.OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS; import android.annotation.NonNull; import android.content.pm.ActivityInfo; import android.window.DesktopModeFlags; /** * Utility functions for app compat in desktop windowing used by both window manager and System UI. * @hide */ public final class DesktopModeCompatUtils { /** * Whether the caption insets should be excluded from configuration for system to handle. * The caller should ensure the activity is in or entering desktop view. * * <p> The treatment is enabled when all the of the following is true: * <li> Any flags to forcibly consume caption insets are enabled. * <li> Top activity have configuration coupled with insets. * <li> Task is not resizeable or per-app override * {@link ActivityInfo#OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS} is enabled. */ public static boolean shouldExcludeCaptionFromAppBounds(@NonNull ActivityInfo info, boolean isResizeable, boolean optOutEdgeToEdge) { return DesktopModeFlags.EXCLUDE_CAPTION_FROM_APP_BOUNDS.isTrue() && isAnyForceConsumptionFlagsEnabled() && !isConfigurationDecoupled(info, optOutEdgeToEdge) && (!isResizeable || info.isChangeEnabled(OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS)); } private static boolean isConfigurationDecoupled(@NonNull ActivityInfo info, boolean optOutEdgeToEdge) { return info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED) && !optOutEdgeToEdge; } private static boolean isAnyForceConsumptionFlagsEnabled() { return DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isTrue() || DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isTrue(); } }
libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt +5 −27 Original line number Diff line number Diff line Loading @@ -19,13 +19,10 @@ package com.android.wm.shell.shared.desktopmode import android.Manifest.permission.SYSTEM_ALERT_WINDOW import android.app.TaskInfo import android.content.Context import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED import android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION import android.content.pm.ActivityInfo.OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS import android.content.pm.PackageManager import android.window.DesktopModeFlags import com.android.internal.R import com.android.internal.policy.DesktopModeCompatUtils /** * Class to decide whether to apply app compat policies in desktop mode. Loading Loading @@ -60,22 +57,11 @@ class DesktopModeCompatPolicy(private val context: Context) { hasFullscreenTransparentPermission(packageName))) && !isTopActivityNoDisplay) /** * Whether the caption insets should be excluded from configuration for system to handle. * * The treatment is enabled when all the of the following is true: * * Any flags to forcibly consume caption insets are enabled. * * Top activity have configuration coupled with insets. * * Task is not resizeable or [ActivityInfo.OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS] * is enabled. */ /** @see DesktopModeCompatUtils.shouldExcludeCaptionFromAppBounds */ fun shouldExcludeCaptionFromAppBounds(taskInfo: TaskInfo): Boolean = DesktopModeFlags.EXCLUDE_CAPTION_FROM_APP_BOUNDS.isTrue && isAnyForceConsumptionFlagsEnabled() && taskInfo.topActivityInfo?.let { isInsetsCoupledWithConfiguration(it) && (!taskInfo.isResizeable || it.isChangeEnabled( OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS )) taskInfo.topActivityInfo?.let { DesktopModeCompatUtils.shouldExcludeCaptionFromAppBounds(it, taskInfo.isResizeable, taskInfo.appCompatTaskInfo.hasOptOutEdgeToEdge()) } ?: false /** Loading Loading @@ -118,12 +104,4 @@ class DesktopModeCompatPolicy(private val context: Context) { */ private fun isPartOfDefaultHomePackageOrNoHomeAvailable(packageName: String?) = defaultHomePackage == null || (packageName != null && packageName == defaultHomePackage) private fun isAnyForceConsumptionFlagsEnabled(): Boolean = DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION_ALWAYS.isTrue || DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION.isTrue private fun isInsetsCoupledWithConfiguration(info: ActivityInfo): Boolean = !(info.isChangeEnabled(OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION) || info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)) }
services/core/java/com/android/server/wm/ActivityRecord.java +1 −1 Original line number Diff line number Diff line Loading @@ -625,7 +625,7 @@ final class ActivityRecord extends WindowToken { @VisibleForTesting final TaskFragment.ConfigOverrideHint mResolveConfigHint; private final boolean mOptOutEdgeToEdge; final boolean mOptOutEdgeToEdge; private static ConstrainDisplayApisConfig sConstrainDisplayApisConfig; Loading
services/core/java/com/android/server/wm/AppCompatUtils.java +1 −0 Original line number Diff line number Diff line Loading @@ -216,6 +216,7 @@ final class AppCompatUtils { AppCompatCameraPolicy.getCameraCompatFreeformMode(top); appCompatTaskInfo.setHasMinAspectRatioOverride(top.mAppCompatController .getDesktopAspectRatioPolicy().hasMinAspectRatioOverride(task)); appCompatTaskInfo.setOptOutEdgeToEdge(top.mOptOutEdgeToEdge); } /** Loading