Introduce config for sandboxing

Bug: 184838306
Bug: 185004937
Test: atest WmTests:SizeCompatTests
Change-Id: I031463f4bf8c8d87a829f1f03603e376bd44c082
This commit is contained in:
Naomi Musgrave
2021-04-08 16:23:53 +01:00
parent 650a27bf2a
commit cbdd8bdb9f
5 changed files with 210 additions and 73 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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",

View File

@@ -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.

View File

@@ -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) {