Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit abac1945 authored by Graciela Wissen Putri's avatar Graciela Wissen Putri
Browse files

[2/n] Exclude caption from initial bounds in core

Desktop tasks launched from taskbar are sent with pending intent and
freeform windowing mode set from shell to core. Currently, exclusion of
caption insets from app bounds are only set in WindowDecoration#relayout
which is too late in the activity lifecycle as configuration has already
been resolved.

Exclude caption insets in task app bounds in launch params calculations
to ensure correct calculations.

Flag: com.android.window.flags.exclude_caption_from_app_bounds
Test: atest DesktopModeLaunchParamsModifierTests
      atest LaunchParamsControllerTests
Bug: 399544381
Change-Id: I411eeacd8d9b37b725f41ca428e20196c8e90904
parent 914eab0d
Loading
Loading
Loading
Loading
+20 −2
Original line number Diff line number Diff line
@@ -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 = {
@@ -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 {}

@@ -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
@@ -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;
+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();
    }
}
+5 −27
Original line number Diff line number Diff line
@@ -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.
@@ -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

    /**
@@ -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))
}
+1 −1
Original line number Diff line number Diff line
@@ -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;

+1 −0
Original line number Diff line number Diff line
@@ -216,6 +216,7 @@ final class AppCompatUtils {
                AppCompatCameraPolicy.getCameraCompatFreeformMode(top);
        appCompatTaskInfo.setHasMinAspectRatioOverride(top.mAppCompatController
                .getDesktopAspectRatioPolicy().hasMinAspectRatioOverride(task));
        appCompatTaskInfo.setOptOutEdgeToEdge(top.mOptOutEdgeToEdge);
    }

    /**
Loading