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

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

Revert^2 [1/n] Sandbox bounds to appBounds in freeform

In freeform, the container bounds are scaled with appBounds. UI can be
cropped if app draws below the insets and bounds extend beyond
appBounds. Sandbox window bounds to appBounds to keep app content within
the container.

Flag: com.android.window.flags.exclude_caption_from_app_bounds
Test: atest SizeCompatTests
Fix: 388011462
Change-Id: I5f7ceddc9615293fe61fcf0cff9f7b391e90d1f5
parent 9d98b2a9
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -8387,6 +8387,7 @@ final class ActivityRecord extends WindowToken {
        mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
        mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
        getResolvedOverrideConfiguration().seq = mConfigurationSeq;
        getResolvedOverrideConfiguration().seq = mConfigurationSeq;


        // TODO(b/392069771): Move to AppCompatSandboxingPolicy.
        // Sandbox max bounds by setting it to the activity bounds, if activity is letterboxed, or
        // Sandbox max bounds by setting it to the activity bounds, if activity is letterboxed, or
        // has or will have mAppCompatDisplayInsets for size compat. Also forces an activity to be
        // has or will have mAppCompatDisplayInsets for size compat. Also forces an activity to be
        // sandboxed or not depending upon the configuration settings.
        // sandboxed or not depending upon the configuration settings.
@@ -8415,6 +8416,9 @@ final class ActivityRecord extends WindowToken {
            resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
            resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
        }
        }


        mAppCompatController.getSandboxingPolicy().sandboxBoundsIfNeeded(resolvedConfig,
                parentWindowingMode);

        applySizeOverrideIfNeeded(
        applySizeOverrideIfNeeded(
                mDisplayContent,
                mDisplayContent,
                info.applicationInfo,
                info.applicationInfo,
+8 −0
Original line number Original line Diff line number Diff line
@@ -44,6 +44,8 @@ class AppCompatController {
    private final AppCompatLetterboxPolicy mLetterboxPolicy;
    private final AppCompatLetterboxPolicy mLetterboxPolicy;
    @NonNull
    @NonNull
    private final AppCompatSizeCompatModePolicy mSizeCompatModePolicy;
    private final AppCompatSizeCompatModePolicy mSizeCompatModePolicy;
    @NonNull
    private final AppCompatSandboxingPolicy mSandboxingPolicy;


    AppCompatController(@NonNull WindowManagerService wmService,
    AppCompatController(@NonNull WindowManagerService wmService,
                        @NonNull ActivityRecord activityRecord) {
                        @NonNull ActivityRecord activityRecord) {
@@ -66,6 +68,7 @@ class AppCompatController {
                mAppCompatOverrides, mTransparentPolicy, wmService.mAppCompatConfiguration);
                mAppCompatOverrides, mTransparentPolicy, wmService.mAppCompatConfiguration);
        mSizeCompatModePolicy = new AppCompatSizeCompatModePolicy(activityRecord,
        mSizeCompatModePolicy = new AppCompatSizeCompatModePolicy(activityRecord,
                mAppCompatOverrides);
                mAppCompatOverrides);
        mSandboxingPolicy = new AppCompatSandboxingPolicy(activityRecord);
    }
    }


    @NonNull
    @NonNull
@@ -143,6 +146,11 @@ class AppCompatController {
        return mSizeCompatModePolicy;
        return mSizeCompatModePolicy;
    }
    }


    @NonNull
    AppCompatSandboxingPolicy getSandboxingPolicy() {
        return mSandboxingPolicy;
    }

    void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
    void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
        getTransparentPolicy().dump(pw, prefix);
        getTransparentPolicy().dump(pw, prefix);
        getLetterboxPolicy().dump(pw, prefix);
        getLetterboxPolicy().dump(pw, prefix);
+65 −0
Original line number Original line 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.server.wm;

import static com.android.server.wm.AppCompatUtils.isInDesktopMode;

import android.annotation.NonNull;
import android.app.WindowConfiguration.WindowingMode;
import android.content.res.Configuration;
import android.graphics.Rect;

import com.android.window.flags.Flags;

/**
 * Encapsulate logic related to sandboxing for app compatibility.
 */
class AppCompatSandboxingPolicy {

    @NonNull
    private final ActivityRecord mActivityRecord;

    AppCompatSandboxingPolicy(@NonNull ActivityRecord activityRecord) {
        mActivityRecord = activityRecord;
    }

    /**
     * In freeform, the container bounds are scaled with app bounds. Activity bounds can be
     * outside of its container bounds if insets are coupled with configuration outside of
     * freeform and maintained in freeform for size compat mode.
     *
     * <p>Sandbox activity bounds in freeform to app bounds to force app to display within the
     * container. This prevents UI cropping when activities can draw below insets which are
     * normally excluded from appBounds before targetSDK < 35
     * (see ConfigurationContainer#applySizeOverrideIfNeeded).
     */
    void sandboxBoundsIfNeeded(@NonNull Configuration resolvedConfig,
            @WindowingMode int windowingMode) {
        if (!Flags.excludeCaptionFromAppBounds()) {
            return;
        }

        if (isInDesktopMode(mActivityRecord.mAtmService.mContext, windowingMode)) {
            Rect appBounds = resolvedConfig.windowConfiguration.getAppBounds();
            if (appBounds == null || appBounds.isEmpty()) {
                // When there is no override bounds, the activity will inherit the bounds from
                // parent.
                appBounds = mActivityRecord.mResolveConfigHint.mParentAppBoundsOverride;
            }
            resolvedConfig.windowConfiguration.setBounds(appBounds);
        }
    }
}
+3 −5
Original line number Original line Diff line number Diff line
@@ -17,14 +17,13 @@
package com.android.server.wm;
package com.android.server.wm;


import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.content.pm.ActivityInfo.SIZE_CHANGES_SUPPORTED_METADATA;
import static android.content.pm.ActivityInfo.SIZE_CHANGES_SUPPORTED_METADATA;
import static android.content.pm.ActivityInfo.SIZE_CHANGES_SUPPORTED_OVERRIDE;
import static android.content.pm.ActivityInfo.SIZE_CHANGES_SUPPORTED_OVERRIDE;
import static android.content.pm.ActivityInfo.SIZE_CHANGES_UNSUPPORTED_METADATA;
import static android.content.pm.ActivityInfo.SIZE_CHANGES_UNSUPPORTED_METADATA;
import static android.content.pm.ActivityInfo.SIZE_CHANGES_UNSUPPORTED_OVERRIDE;
import static android.content.pm.ActivityInfo.SIZE_CHANGES_UNSUPPORTED_OVERRIDE;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;


import static com.android.server.wm.DesktopModeHelper.canEnterDesktopMode;
import static com.android.server.wm.AppCompatUtils.isInDesktopMode;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
@@ -545,9 +544,8 @@ class AppCompatSizeCompatModePolicy {
        // Allow an application to be up-scaled if its window is smaller than its
        // Allow an application to be up-scaled if its window is smaller than its
        // original container or if it's a freeform window in desktop mode.
        // original container or if it's a freeform window in desktop mode.
        boolean shouldAllowUpscaling = !(contentW <= viewportW && contentH <= viewportH)
        boolean shouldAllowUpscaling = !(contentW <= viewportW && contentH <= viewportH)
                || (canEnterDesktopMode(mActivityRecord.mAtmService.mContext)
                || isInDesktopMode(mActivityRecord.mAtmService.mContext,
                && newParentConfig.windowConfiguration.getWindowingMode()
                newParentConfig.windowConfiguration.getWindowingMode());
                    == WINDOWING_MODE_FREEFORM);
        return shouldAllowUpscaling ? Math.min(
        return shouldAllowUpscaling ? Math.min(
                (float) viewportW / contentW, (float) viewportH / contentH) : 1f;
                (float) viewportW / contentW, (float) viewportH / contentH) : 1f;
    }
    }
+12 −0
Original line number Original line Diff line number Diff line
@@ -16,16 +16,20 @@


package com.android.server.wm;
package com.android.server.wm;


import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;


import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.DesktopModeHelper.canEnterDesktopMode;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.AppCompatTaskInfo;
import android.app.AppCompatTaskInfo;
import android.app.CameraCompatTaskInfo;
import android.app.CameraCompatTaskInfo;
import android.app.TaskInfo;
import android.app.TaskInfo;
import android.app.WindowConfiguration.WindowingMode;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Rect;
import android.view.InsetsSource;
import android.view.InsetsSource;
@@ -276,6 +280,14 @@ final class AppCompatUtils {
        inOutConfig.windowConfiguration.getAppBounds().offset(offsetX, offsetY);
        inOutConfig.windowConfiguration.getAppBounds().offset(offsetX, offsetY);
    }
    }


    /**
     * Return {@code true} if window is currently in desktop mode.
     */
    static boolean isInDesktopMode(@NonNull Context context,
            @WindowingMode int parentWindowingMode) {
        return parentWindowingMode == WINDOWING_MODE_FREEFORM && canEnterDesktopMode(context);
    }

    private static void clearAppCompatTaskInfo(@NonNull AppCompatTaskInfo info) {
    private static void clearAppCompatTaskInfo(@NonNull AppCompatTaskInfo info) {
        info.topActivityLetterboxVerticalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
        info.topActivityLetterboxVerticalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
        info.topActivityLetterboxHorizontalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
        info.topActivityLetterboxHorizontalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
Loading