diff options
| -rw-r--r-- | core/api/test-current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/content/pm/ActivityInfo.java | 43 | ||||
| -rw-r--r-- | data/etc/services.core.protolog.json | 12 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/ActivityRecord.java | 18 | ||||
| -rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java | 208 |
5 files changed, 210 insertions, 73 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index e449728ca0a8..06b967233ffc 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -773,8 +773,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; diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index fa9142ca9449..fc0e214a645f 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -961,6 +961,29 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { 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: * OVERRIDE_MIN_ASPECT_RATIO_MEDIUM @@ -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; diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 81f1021c6eab..7ed791d6ca71 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -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", diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 3e3ff1f3d9f2..6fb356a5c739 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1098,6 +1098,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); @@ -7103,7 +7105,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()) { @@ -7113,11 +7116,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()); @@ -7514,12 +7521,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. diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index ee1d39328555..b80388782e59 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -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,19 +746,111 @@ 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}) public void testOverrideMinAspectRatioMedium() { @@ -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) { |