Per-app configuration for force resizing

We're defining a new compat framework change id that indicates whether a
given app should be force resized. This is treated the same as
supportsSizeChanges metadata.

Bug: 174042936
Test: atest WmTests:SizeCompatTests
Change-Id: I6ef3ec11171140ca5a244f2185a3710d9fec7ae9
This commit is contained in:
Benjamin Franz
2020-11-16 16:56:13 +00:00
parent a0b0cf2b51
commit 06bb87d8fe
4 changed files with 111 additions and 4 deletions

View File

@@ -18,6 +18,9 @@ package android.content.pm;
import android.annotation.IntDef;
import android.annotation.TestApi;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
@@ -27,6 +30,7 @@ import android.content.res.TypedArray;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.util.Printer;
import java.lang.annotation.Retention;
@@ -865,6 +869,47 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
Configuration.NATIVE_CONFIG_COLOR_MODE, // COLOR_MODE
};
/**
* This change id forces the packages it is applied to to be resizable. We only allow resizing
* in fullscreen windowing mode, but not forcing the app into resizable multi-windowing mode.
* @hide
*/
@ChangeId
@Disabled
public static final long FORCE_RESIZE_APP = 174042936L; // number refers to buganizer id
/**
* Return value for {@link #supportsSizeChanges()} indicating that this activity does not
* support size changes.
* @hide
*/
public static final int SIZE_CHANGES_UNSUPPORTED = 0;
/**
* Return value for {@link #supportsSizeChanges()} indicating that this activity supports size
* changes due to the android.supports_size_changes metadata flag being set either on
* application or on activity level.
* @hide
*/
public static final int SIZE_CHANGES_SUPPORTED_METADATA = 1;
/**
* Return value for {@link #supportsSizeChanges()} indicating that this activity has been
* overridden to support size changes through the compat framework change id
* {@link #FORCE_RESIZE_APP}.
* @hide
*/
public static final int SIZE_CHANGES_SUPPORTED_OVERRIDE = 2;
/** @hide */
@IntDef(prefix = { "SIZE_CHANGES_" }, value = {
SIZE_CHANGES_UNSUPPORTED,
SIZE_CHANGES_SUPPORTED_METADATA,
SIZE_CHANGES_SUPPORTED_OVERRIDE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SizeChangesSupportMode {}
/**
* Convert Java change bits to native.
*
@@ -1146,6 +1191,25 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
return (flags & FLAG_SUPPORTS_PICTURE_IN_PICTURE) != 0;
}
/**
* Returns whether the activity supports size changes.
* @hide
*/
@SizeChangesSupportMode
public int supportsSizeChanges() {
if (supportsSizeChanges) {
return SIZE_CHANGES_SUPPORTED_METADATA;
}
if (CompatChanges.isChangeEnabled(FORCE_RESIZE_APP,
applicationInfo.packageName,
UserHandle.getUserHandleForUid(applicationInfo.uid))) {
return SIZE_CHANGES_SUPPORTED_OVERRIDE;
}
return SIZE_CHANGES_UNSUPPORTED;
}
/** @hide */
@UnsupportedAppUsage
public static boolean isResizeableMode(int mode) {
@@ -1186,6 +1250,20 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
}
}
/** @hide */
public static String sizeChangesSupportModeToString(@SizeChangesSupportMode int mode) {
switch (mode) {
case SIZE_CHANGES_UNSUPPORTED:
return "SIZE_CHANGES_UNSUPPORTED";
case SIZE_CHANGES_SUPPORTED_METADATA:
return "SIZE_CHANGES_SUPPORTED_METADATA";
case SIZE_CHANGES_SUPPORTED_OVERRIDE:
return "SIZE_CHANGES_SUPPORTED_OVERRIDE";
default:
return "unknown=" + mode;
}
}
public void dump(Printer pw, String prefix) {
dump(pw, prefix, DUMP_FLAG_ALL);
}

View File

@@ -1009,9 +1009,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (info.minAspectRatio != 0) {
pw.println(prefix + "minAspectRatio=" + info.minAspectRatio);
}
if (info.supportsSizeChanges) {
pw.println(prefix + "supportsSizeChanges=true");
}
pw.println(prefix + "supportsSizeChanges="
+ ActivityInfo.sizeChangesSupportModeToString(info.supportsSizeChanges()));
if (info.configChanges != 0) {
pw.println(prefix + "configChanges=0x" + Integer.toHexString(info.configChanges));
}
@@ -6539,7 +6538,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* aspect ratio.
*/
boolean shouldUseSizeCompatMode() {
if (info.supportsSizeChanges) {
if (info.supportsSizeChanges() != ActivityInfo.SIZE_CHANGES_UNSUPPORTED) {
return false;
}
if (inMultiWindowMode() || getWindowConfiguration().hasWindowDecorCaption()) {

View File

@@ -47,6 +47,7 @@ android_test {
"testables",
"ub-uiautomator",
"hamcrest-library",
"platform-compat-test-rules",
],
libs: [

View File

@@ -49,6 +49,8 @@ import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.TaskStackListener;
import android.app.WindowConfiguration;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -58,7 +60,11 @@ import android.view.WindowManager;
import androidx.test.filters.MediumTest;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import java.util.ArrayList;
@@ -73,6 +79,9 @@ import java.util.ArrayList;
@Presubmit
@RunWith(WindowTestRunner.class)
public class SizeCompatTests extends WindowTestsBase {
@Rule
public TestRule compatChangeRule = new PlatformCompatChangeRule();
private Task mTask;
private ActivityRecord mActivity;
@@ -534,6 +543,26 @@ public class SizeCompatTests extends WindowTestsBase {
assertFalse(activity.shouldUseSizeCompatMode());
}
@Test
@EnableCompatChanges({ActivityInfo.FORCE_RESIZE_APP})
public void testNoSizeCompatWhenPerAppOverrideSet() {
setUpDisplaySizeWithApp(1000, 2500);
// Make the task root resizable.
mActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
// Create a size compat activity on the same task.
final ActivityRecord activity = new ActivityBuilder(mAtm)
.setTask(mTask)
.setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
.setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
.setComponent(ComponentName.createRelative(mContext,
SizeCompatTests.class.getName()))
.setUid(android.os.Process.myUid())
.build();
assertFalse(activity.shouldUseSizeCompatMode());
}
@Test
public void testLaunchWithFixedRotationTransform() {
final int dw = 1000;