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

Commit 4d3f1c56 authored by Naomi Musgrave's avatar Naomi Musgrave
Browse files

Sandbox letterbox and size compat apps

Sandbox Display#getRealSize and WindowManager
bounds when letterbox or size compat mode are
applied to the configuration. Display uses
this field to provide the sandboxed display
size.

Test: atest WindowConfigurationTests
Test: atest FrameworksMockingCoreTests:android.view.DisplayTests
Test: atest WmTests:SizeCompatTests
Bug: 171386167
Change-Id: I6f78edcd9214b52ab0708e3892bc86ee05bb5b9a
parent 8812ace3
Loading
Loading
Loading
Loading
+54 −26
Original line number Diff line number Diff line
@@ -25,8 +25,8 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.app.KeyguardManager;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -59,12 +59,8 @@ import java.util.List;
 * an application window, excluding the system decorations.  The application display area may
 * be smaller than the real display area because the system subtracts the space needed
 * for decor elements such as the status bar.  Use {@link WindowMetrics#getBounds()} to query the
 * application window bounds.</li>
 * <li>The real display area specifies the part of the display that contains content
 * including the system decorations.  Even so, the real display area may be smaller than the
 * physical size of the display if the window manager is emulating a smaller display
 * using (adb shell wm size).  Use the following methods to query the
 * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
 * application window bounds. Generally, use {@link WindowManager#getCurrentWindowMetrics()} to
 * query the metrics and perform UI-related actions.</li>
 * </ul>
 * </p><p>
 * A logical display does not necessarily represent a particular physical display device
@@ -677,9 +673,9 @@ public final class Display {
    @UnsupportedAppUsage
    public DisplayAdjustments getDisplayAdjustments() {
        if (mResources != null) {
            final DisplayAdjustments currentAdjustements = mResources.getDisplayAdjustments();
            if (!mDisplayAdjustments.equals(currentAdjustements)) {
                mDisplayAdjustments = new DisplayAdjustments(currentAdjustements);
            final DisplayAdjustments currentAdjustments = mResources.getDisplayAdjustments();
            if (!mDisplayAdjustments.equals(currentAdjustments)) {
                mDisplayAdjustments = new DisplayAdjustments(currentAdjustments);
            }
        }

@@ -1191,30 +1187,34 @@ public final class Display {
    }

    /**
     * Gets the real size of the display without subtracting any window decor or
     * applying any compatibility scale factors.
     * Provides the largest {@link Point outSize} an app may expect in the current system state,
     * without subtracting any window decor.
     * <p>
     * The size is adjusted based on the current rotation of the display.
     * The size describes the largest potential area the window might occupy. The size is adjusted
     * based on the current rotation of the display.
     * </p><p>
     * The real size may be smaller than the physical size of the screen when the
     * window manager is emulating a smaller display (using adb shell wm size).
     * </p><p>
     * In general, {@link #getRealSize(Point)} and {@link WindowManager#getMaximumWindowMetrics()}
     * report the same bounds except that certain areas of the display may not be available to
     * windows created in the {@link WindowManager}'s {@link Context}.
     *
     * For example, imagine a device which has a multi-task mode that limits windows to half of the
     * screen. In this case, {@link WindowManager#getMaximumWindowMetrics()} reports the
     * bounds of the screen half where the window is located, while {@link #getRealSize(Point)}
     * still reports the bounds of the whole display.
     * </p>
     *
     * @param outSize Set to the real size of the display.
     *
     * @see WindowManager#getMaximumWindowMetrics()
     */
    public void getRealSize(Point outSize) {
        synchronized (this) {
            updateDisplayInfoLocked();
            if (shouldReportMaxBounds()) {
                final Rect bounds = mResources.getConfiguration()
                        .windowConfiguration.getMaxBounds();
                outSize.x = bounds.width();
                outSize.y = bounds.height();
                if (DEBUG) {
                    Log.d(TAG, "getRealSize determined from max bounds: " + outSize
                            + " for uid " + Process.myUid());
                }
                // Skip adjusting by fixed rotation, since if it is necessary, the configuration
                // should already reflect the expected rotation.
                return;
            }
            outSize.x = mDisplayInfo.logicalWidth;
            outSize.y = mDisplayInfo.logicalHeight;
            if (mMayAdjustByFixedRotation) {
@@ -1224,9 +1224,11 @@ public final class Display {
    }

    /**
     * Gets display metrics based on the real size of this display.
     * Provides the largest {@link DisplayMetrics outMetrics} an app may expect in the current
     * system state, without subtracting any window decor.
     * <p>
     * The size is adjusted based on the current rotation of the display.
     * The size describes the largest potential area the window might occupy. The size is adjusted
     * based on the current rotation of the display.
     * </p><p>
     * The real size may be smaller than the physical size of the screen when the
     * window manager is emulating a smaller display (using adb shell wm size).
@@ -1237,6 +1239,18 @@ public final class Display {
    public void getRealMetrics(DisplayMetrics outMetrics) {
        synchronized (this) {
            updateDisplayInfoLocked();
            if (shouldReportMaxBounds()) {
                mDisplayInfo.getMaxBoundsMetrics(outMetrics,
                        CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO,
                        mResources.getConfiguration());
                if (DEBUG) {
                    Log.d(TAG, "getRealMetrics determined from max bounds: " + outMetrics
                            + " for uid " + Process.myUid());
                }
                // Skip adjusting by fixed rotation, since if it is necessary, the configuration
                // should already reflect the expected rotation.
                return;
            }
            mDisplayInfo.getLogicalMetrics(outMetrics,
                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
            if (mMayAdjustByFixedRotation) {
@@ -1245,6 +1259,20 @@ public final class Display {
        }
    }

    /**
     * Determines if {@link WindowConfiguration#getMaxBounds()} should be reported as the
     * display dimensions. The max bounds field may be smaller than the logical dimensions
     * when apps need to be sandboxed.
     * @return {@code true} when max bounds should be applied.
     */
    private boolean shouldReportMaxBounds() {
        if (mResources == null) {
            return false;
        }
        final Configuration config = mResources.getConfiguration();
        return config != null && !config.windowConfiguration.getMaxBounds().isEmpty();
    }

    /**
     * Gets the state of the display, such as whether it is on or off.
     *
+19 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.view.DisplayInfoProto.LOGICAL_WIDTH;
import static android.view.DisplayInfoProto.NAME;

import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -605,11 +606,29 @@ public final class DisplayInfo implements Parcelable {
        getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight);
    }

    /**
     * Populates {@code outMetrics} with details of the logical display. Bounds are limited
     * by the logical size of the display.
     *
     * @param outMetrics the {@link DisplayMetrics} to be populated
     * @param compatInfo the {@link CompatibilityInfo} to be applied
     * @param configuration the {@link Configuration}
     */
    public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
            Configuration configuration) {
        getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight);
    }

    /**
     * Similar to {@link #getLogicalMetrics}, but the limiting bounds are determined from
     * {@link WindowConfiguration#getMaxBounds()}
     */
    public void getMaxBoundsMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
            Configuration configuration) {
        Rect bounds = configuration.windowConfiguration.getMaxBounds();
        getMetricsWithSize(outMetrics, compatInfo, configuration, bounds.width(), bounds.height());
    }

    public int getNaturalWidth() {
        return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
                logicalWidth : logicalHeight;
+527 −0

File added.

Preview size limit exceeded, changes collapsed.

+12 −6
Original line number Diff line number Diff line
@@ -1903,12 +1903,6 @@
      "group": "WM_DEBUG_FOCUS_LIGHT",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "123161180": {
      "message": "SEVER CHILDREN",
      "level": "INFO",
      "group": "WM_SHOW_TRANSACTIONS",
      "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
    },
    "140319294": {
      "message": "IME target changed within ActivityRecord",
      "level": "DEBUG",
@@ -2143,6 +2137,12 @@
      "group": "WM_ERROR",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "332390227": {
      "message": "Sandbox max bounds for uid %s to bounds %s due to letterboxing? %s mismatch with parent bounds? %s size compat mode %s",
      "level": "DEBUG",
      "group": "WM_DEBUG_CONFIGURATION",
      "at": "com\/android\/server\/wm\/ActivityRecord.java"
    },
    "342460966": {
      "message": "DRAG %s: pos=(%d,%d)",
      "level": "INFO",
@@ -2623,6 +2623,12 @@
      "group": "WM_DEBUG_WINDOW_ORGANIZER",
      "at": "com\/android\/server\/wm\/WindowOrganizerController.java"
    },
    "910200295": {
      "message": "Sandbox max bounds due to mismatched orientation with parent, to %s vs DisplayArea %s",
      "level": "DEBUG",
      "group": "WM_DEBUG_CONFIGURATION",
      "at": "com\/android\/server\/wm\/Task.java"
    },
    "913494177": {
      "message": "removeAllWindowsIfPossible: removing win=%s",
      "level": "WARN",
+31 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.wm;

import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
@@ -81,6 +82,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.EMPTY;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -201,6 +203,7 @@ import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.ACTIVITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -266,6 +269,7 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.permission.PermissionManager;
import android.service.dreams.DreamActivity;
import android.service.dreams.DreamManagerInternal;
import android.service.voice.IVoiceInteractionSession;
@@ -6737,6 +6741,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // layout traversals.
        mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
        getResolvedOverrideConfiguration().seq = mConfigurationSeq;

        // Sandbox max bounds by setting it to the app bounds, if activity is letterboxed or in
        // size compat mode.
        if (providesMaxBounds()) {
            if (DEBUG_CONFIGURATION) {
                ProtoLog.d(WM_DEBUG_CONFIGURATION, "Sandbox max bounds for uid %s to bounds %s "
                        + "due to letterboxing? %s mismatch with parent bounds? %s size compat "
                        + "mode %s", getUid(),
                        resolvedConfig.windowConfiguration.getBounds(), mLetterbox != null,
                        !matchParentBounds(), inSizeCompatMode());
            }
            resolvedConfig.windowConfiguration
                    .setMaxBounds(resolvedConfig.windowConfiguration.getBounds());
        }
    }

    /**
@@ -6920,6 +6938,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return super.getBounds();
    }

    @Override
    public boolean providesMaxBounds() {
        // System and SystemUI should always be able to access the physical display bounds,
        // so do not provide it with the overridden maximum bounds.
        // TODO(b/179179513) check WindowState#mOwnerCanAddInternalSystemWindow instead
        if (getUid() == SYSTEM_UID || PermissionManager.checkPermission(INTERNAL_SYSTEM_WINDOW,
                getPid(), info.applicationInfo.uid) == PERMISSION_GRANTED) {
            return false;
        }
        // Max bounds should be sandboxed when this is letterboxed or in size compat mode.
        return mLetterbox != null || !matchParentBounds() || inSizeCompatMode();
    }

    @VisibleForTesting
    @Override
    Rect getAnimationBounds(int appRootTaskClipMode) {
Loading