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

Commit 9ed42319 authored by Naomi Musgrave's avatar Naomi Musgrave Committed by Automerger Merge Worker
Browse files

Merge "Introduce config for sandboxing" into sc-dev am: 692496d9

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14127228

Change-Id: I540c2d9a886fdf75b8280924845d61cc7cb11b0d
parents 635e1fbd 692496d9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -783,8 +783,10 @@ package android.content.pm {

  public class ActivityInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable {
    method public static boolean isTranslucentOrFloating(android.content.res.TypedArray);
    field public static final long ALWAYS_SANDBOX_DISPLAY_APIS = 185004937L; // 0xb06f389L
    field public static final long FORCE_NON_RESIZE_APP = 181136395L; // 0xacbec0bL
    field public static final long FORCE_RESIZE_APP = 174042936L; // 0xa5faf38L
    field public static final long NEVER_SANDBOX_DISPLAY_APIS = 184838306L; // 0xb0468a2L
    field public static final long OVERRIDE_MIN_ASPECT_RATIO = 174042980L; // 0xa5faf64L
    field public static final long OVERRIDE_MIN_ASPECT_RATIO_LARGE = 180326787L; // 0xabf9183L
    field public static final float OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE = 1.7777778f;
+43 −0
Original line number Diff line number Diff line
@@ -960,6 +960,29 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
    @Retention(RetentionPolicy.SOURCE)
    public @interface SizeChangesSupportMode {}

    /**
     * This change id forces the packages it is applied to never have Display API sandboxing
     * applied for a letterbox or SCM activity. The Display APIs will continue to provide
     * DisplayArea bounds.
     * @hide
     */
    @ChangeId
    @Overridable
    @Disabled
    @TestApi
    public static final long NEVER_SANDBOX_DISPLAY_APIS = 184838306L; // buganizer id

    /**
     * This change id forces the packages it is applied to always have Display API sandboxing
     * applied, regardless of windowing mode. The Display APIs will always provide the app bounds.
     * @hide
     */
    @ChangeId
    @Overridable
    @Disabled
    @TestApi
    public static final long ALWAYS_SANDBOX_DISPLAY_APIS = 185004937L; // buganizer id

    /**
     * This change id is the gatekeeper for all treatments that force a given min aspect ratio.
     * Enabling this change will allow the following min aspect ratio treatments to be applied:
@@ -1325,6 +1348,26 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
        return SIZE_CHANGES_UNSUPPORTED_METADATA;
    }

    /**
     * Returns if the activity should never be sandboxed to the activity window bounds.
     * @hide
     */
    public boolean neverSandboxDisplayApis() {
        return CompatChanges.isChangeEnabled(NEVER_SANDBOX_DISPLAY_APIS,
                applicationInfo.packageName,
                UserHandle.getUserHandleForUid(applicationInfo.uid));
    }

    /**
     * Returns if the activity should always be sandboxed to the activity window bounds.
     * @hide
     */
    public boolean alwaysSandboxDisplayApis() {
        return CompatChanges.isChangeEnabled(ALWAYS_SANDBOX_DISPLAY_APIS,
                applicationInfo.packageName,
                UserHandle.getUserHandleForUid(applicationInfo.uid));
    }

    /** @hide */
    public void setMaxAspectRatio(float maxAspectRatio) {
        this.mMaxAspectRatio = maxAspectRatio;
+6 −6
Original line number Diff line number Diff line
@@ -1735,6 +1735,12 @@
      "group": "WM_DEBUG_IME",
      "at": "com\/android\/server\/wm\/InsetsSourceProvider.java"
    },
    "-108977760": {
      "message": "Sandbox max bounds for uid %s to bounds %s. config to never sandbox = %s, config to always sandbox = %s, letterboxing from mismatch with parent bounds = %s, has mCompatDisplayInsets = %s, should create compatDisplayInsets = %s",
      "level": "DEBUG",
      "group": "WM_DEBUG_CONFIGURATION",
      "at": "com\/android\/server\/wm\/ActivityRecord.java"
    },
    "-106400104": {
      "message": "Preload recents with %s",
      "level": "DEBUG",
@@ -2887,12 +2893,6 @@
      "group": "WM_DEBUG_BOOT",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "1237719089": {
      "message": "Sandbox max bounds for uid %s to bounds %s. letterboxing from mismatch with parent bounds = %s, has mCompatDisplayInsets = %s, should create compatDisplayInsets = %s",
      "level": "DEBUG",
      "group": "WM_DEBUG_CONFIGURATION",
      "at": "com\/android\/server\/wm\/ActivityRecord.java"
    },
    "1246035185": {
      "message": "stopFreezingDisplayLocked: Returning waitingForConfig=%b, waitingForRemoteRotation=%b, mAppsFreezingScreen=%d, mWindowsFreezingScreen=%d, mClientFreezingScreen=%b, mOpeningApps.size()=%d",
      "level": "DEBUG",
+16 −2
Original line number Diff line number Diff line
@@ -1090,6 +1090,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            if (info.configChanges != 0) {
                pw.println(prefix + "configChanges=0x" + Integer.toHexString(info.configChanges));
            }
            pw.println(prefix + "neverSandboxDisplayApis=" + info.neverSandboxDisplayApis());
            pw.println(prefix + "alwaysSandboxDisplayApis=" + info.alwaysSandboxDisplayApis());
        }
        if (mLastParentBeforePip != null) {
            pw.println(prefix + "lastParentTaskIdBeforePip=" + mLastParentBeforePip.mTaskId);
@@ -6899,7 +6901,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        getResolvedOverrideConfiguration().seq = mConfigurationSeq;

        // Sandbox max bounds by setting it to the activity bounds, if activity is letterboxed, or
        // has or will have mCompatDisplayInsets for size compat.
        // has or will have mCompatDisplayInsets for size compat. Also forces an activity to be
        // sandboxed or not depending upon the configuration settings.
        if (providesMaxBounds()) {
            mTmpBounds.set(resolvedConfig.windowConfiguration.getBounds());
            if (mTmpBounds.isEmpty()) {
@@ -6909,11 +6912,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            }
            if (DEBUG_CONFIGURATION) {
                ProtoLog.d(WM_DEBUG_CONFIGURATION, "Sandbox max bounds for uid %s to bounds %s. "
                                + "config to never sandbox = %s, "
                                + "config to always sandbox = %s, "
                                + "letterboxing from mismatch with parent bounds = %s, "
                                + "has mCompatDisplayInsets = %s, "
                                + "should create compatDisplayInsets = %s",
                        getUid(),
                        mTmpBounds,
                        info.neverSandboxDisplayApis(),
                        info.alwaysSandboxDisplayApis(),
                        !matchParentBounds(),
                        mCompatDisplayInsets != null,
                        shouldCreateCompatDisplayInsets());
@@ -7311,12 +7318,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (mDisplayContent != null && !mDisplayContent.sandboxDisplayApis()) {
            return false;
        }
        // Never apply sandboxing to an app that should be explicitly excluded from the config.
        if (info != null && info.neverSandboxDisplayApis()) {
            return false;
        }
        // Always apply sandboxing to an app that should be explicitly included from the config.
        if (info != null && info.alwaysSandboxDisplayApis()) {
            return true;
        }
        // Max bounds should be sandboxed where an activity is letterboxed (activity bounds will be
        // smaller than task bounds).
        if (!matchParentBounds()) {
            return true;
        }

        // Max bounds should be sandboxed when an activity should have compatDisplayInsets, and it
        // will keep the same bounds and screen configuration when it was first launched regardless
        // how its parent window changes, so that the sandbox API will provide a consistent result.
+143 −65
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ import android.app.WindowConfiguration;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -67,6 +68,7 @@ import android.view.WindowManager;

import androidx.test.filters.MediumTest;

import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;

import org.junit.Rule;
@@ -662,15 +664,8 @@ public class SizeCompatTests extends WindowTestsBase {
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
                .setSupportsSizeChanges(true)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */true,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
    }

@@ -682,15 +677,8 @@ public class SizeCompatTests extends WindowTestsBase {
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
                .setSupportsSizeChanges(false)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        assertTrue(activity.shouldCreateCompatDisplayInsets());
    }

@@ -702,15 +690,8 @@ public class SizeCompatTests extends WindowTestsBase {
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setResizeMode(ActivityInfo.RESIZE_MODE_RESIZEABLE)
                .setSupportsSizeChanges(false)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_RESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
    }

@@ -723,15 +704,8 @@ public class SizeCompatTests extends WindowTestsBase {
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
                .setSupportsSizeChanges(false)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
    }

@@ -744,15 +718,8 @@ public class SizeCompatTests extends WindowTestsBase {
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
                .setSupportsSizeChanges(false)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
    }

@@ -765,15 +732,8 @@ public class SizeCompatTests extends WindowTestsBase {
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setResizeMode(ActivityInfo.RESIZE_MODE_RESIZEABLE)
                .setSupportsSizeChanges(true)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */true,
                RESIZE_MODE_RESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        assertTrue(activity.shouldCreateCompatDisplayInsets());
    }

@@ -786,18 +746,110 @@ public class SizeCompatTests extends WindowTestsBase {
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setResizeMode(ActivityInfo.RESIZE_MODE_RESIZEABLE)
                .setSupportsSizeChanges(true)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */true,
                RESIZE_MODE_RESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        assertTrue(activity.shouldCreateCompatDisplayInsets());
    }

    @Test
    @EnableCompatChanges({ActivityInfo.NEVER_SANDBOX_DISPLAY_APIS})
    public void testNeverSandboxDisplayApis_configEnabled_sandboxingNotApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should not be sandboxed, even though it is letterboxed.
        assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertThat(activity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(activity.getDisplayArea().getBounds());
    }

    @Test
    @DisableCompatChanges({ActivityInfo.NEVER_SANDBOX_DISPLAY_APIS})
    public void testNeverSandboxDisplayApis_configDisabled_sandboxingApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should be sandboxed due to letterboxed and the config being disabled.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
    public void testAlwaysSandboxDisplayApis_configEnabled_sandboxingApplied_unresizable() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should be sandboxed due to letterboxed and the config being enabled.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    @DisableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
    public void testAlwaysSandboxDisplayApis_configDisabled_sandboxingNotApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds be sandboxed due to letterbox and the config being disabled.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
    public void testAlwaysSandboxDisplayApis_configEnabled_sandboxingApplied_resizableSplit() {
        setUpDisplaySizeWithApp(1000, 2800);
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_RESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, activity.getDisplayContent());

        // Activity max bounds should be sandboxed due the config being enabled.
        assertFalse(activity.inSizeCompatMode());
        assertActivityMaxBoundsSandboxed(activity);

        // Move activity to split screen which takes half of the screen.
        mTask.reparent(organizer.mPrimary, POSITION_TOP,
                false /*moveParents*/, "test");
        organizer.mPrimary.setBounds(0, 0, 1000, 1400);
        assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, mTask.getWindowingMode());
        assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, activity.getWindowingMode());

        // Resizable activity is sandboxed due to config being enabled.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
@@ -1675,6 +1727,24 @@ public class SizeCompatTests extends WindowTestsBase {
        displayPolicy.layoutWindowLw(statusBar, null, displayContent.mDisplayFrames);
    }

    /**
     * Returns an ActivityRecord instance with the specified attributes on the same task. By
     * constructing the ActivityRecord, forces {@link ActivityInfo} to be loaded with the compat
     * config settings.
     */
    private ActivityRecord buildActivityRecord(boolean supportsSizeChanges, int resizeMode,
            @ScreenOrientation int screenOrientation) {
        return new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setResizeMode(resizeMode)
                .setSupportsSizeChanges(supportsSizeChanges)
                .setScreenOrientation(screenOrientation)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();
    }

    static void prepareUnresizable(ActivityRecord activity, int screenOrientation) {
        prepareUnresizable(activity, -1 /* maxAspect */, screenOrientation);
    }
@@ -1743,9 +1813,17 @@ public class SizeCompatTests extends WindowTestsBase {
     * bounds are sandboxed.
     */
    private void assertActivityMaxBoundsSandboxed() {
        assertActivityMaxBoundsSandboxed(mActivity);
    }

    /**
     * Asserts activity-level letterbox or size compat mode size compat mode on the specified
     * activity, so activity max bounds are sandboxed.
     */
    private void assertActivityMaxBoundsSandboxed(ActivityRecord activity) {
        // Activity max bounds are sandboxed due to size compat mode.
        assertThat(mActivity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(mActivity.getWindowConfiguration().getBounds());
        assertThat(activity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(activity.getWindowConfiguration().getBounds());
    }

    static Configuration rotateDisplay(DisplayContent display, int rotation) {