Merge "Add minAspectRatio"

This commit is contained in:
Adrian Roos
2018-12-14 18:44:27 +00:00
committed by Android (Google) Code Review
7 changed files with 152 additions and 15 deletions

View File

@@ -940,6 +940,7 @@ package android {
field public static final int menuCategory = 16843230; // 0x10101de
field public static final int mimeType = 16842790; // 0x1010026
field public static final int min = 16844089; // 0x1010539
field public static final int minAspectRatio = 16844193; // 0x10105a1
field public static final int minDate = 16843583; // 0x101033f
field public static final int minEms = 16843098; // 0x101015a
field public static final int minHeight = 16843072; // 0x1010140

View File

@@ -235,6 +235,15 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
*/
public float maxAspectRatio;
/**
* Value indicating the minimum aspect ratio the activity supports.
* <p>
* 0 means unset.
* @See {@link android.R.attr#minAspectRatio}.
* @hide
*/
public float minAspectRatio;
/**
* Name of the VrListenerService component to run for this activity.
* @see android.R.attr#enableVrMode
@@ -979,6 +988,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
rotationAnimation = orig.rotationAnimation;
colorMode = orig.colorMode;
maxAspectRatio = orig.maxAspectRatio;
minAspectRatio = orig.minAspectRatio;
}
/**
@@ -1142,6 +1152,9 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
if (maxAspectRatio != 0) {
pw.println(prefix + "maxAspectRatio=" + maxAspectRatio);
}
if (minAspectRatio != 0) {
pw.println(prefix + "minAspectRatio=" + minAspectRatio);
}
super.dumpBack(pw, prefix, dumpFlags);
}
@@ -1190,6 +1203,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
dest.writeInt(rotationAnimation);
dest.writeInt(colorMode);
dest.writeFloat(maxAspectRatio);
dest.writeFloat(minAspectRatio);
}
/**
@@ -1309,6 +1323,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
rotationAnimation = source.readInt();
colorMode = source.readInt();
maxAspectRatio = source.readFloat();
minAspectRatio = source.readFloat();
}
/**

View File

@@ -712,6 +712,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
*/
public float maxAspectRatio;
/**
* Value indicating the minimum aspect ratio the application supports.
* <p>
* 0 means unset.
* @see {@link android.R.attr#minAspectRatio}.
* @hide
*/
public float minAspectRatio;
/** @removed */
@Deprecated
public String volumeUuid;

View File

@@ -30,6 +30,7 @@ import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
@@ -162,6 +163,8 @@ public class PackageParser {
SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false);
private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO = 1.333f;
private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH = 1f;
// TODO: switch outError users to PackageParserException
// TODO: refactor "codePath" to "apkPath"
@@ -3673,6 +3676,7 @@ public class PackageParser {
}
ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);
ai.minAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_minAspectRatio, 0);
ai.networkSecurityConfigRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
@@ -3995,6 +3999,7 @@ public class PackageParser {
// Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
// every activity info has had a chance to set it from its attributes.
setMaxAspectRatio(owner);
setMinAspectRatio(owner);
PackageBackwardCompatibility.modifySharedLibraries(owner);
@@ -4492,6 +4497,13 @@ public class PackageParser {
0 /*default*/));
}
if (sa.hasValue(R.styleable.AndroidManifestActivity_minAspectRatio)
&& sa.getType(R.styleable.AndroidManifestActivity_minAspectRatio)
== TypedValue.TYPE_FLOAT) {
a.setMinAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_minAspectRatio,
0 /*default*/));
}
a.info.lockTaskLaunchMode =
sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
@@ -4750,6 +4762,34 @@ public class PackageParser {
}
}
/**
* Sets every the max aspect ratio of every child activity that doesn't already have an aspect
* ratio set.
*/
private void setMinAspectRatio(Package owner) {
final float minAspectRatio;
if (owner.applicationInfo.minAspectRatio != 0) {
// Use the application max aspect ration as default if set.
minAspectRatio = owner.applicationInfo.minAspectRatio;
} else {
// Default to (1.33) 4:3 aspect ratio for pre-Q apps and unset for Q and greater.
// NOTE: 4:3 was the min aspect ratio Android devices can support pre-Q per the CDD,
// except for watches which always supported 1:1.
minAspectRatio = owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q
? 0
: mCallback.hasFeature(FEATURE_WATCH)
? DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH
: DEFAULT_PRE_Q_MIN_ASPECT_RATIO;
}
for (Activity activity : owner.activities) {
if (activity.hasMinAspectRatio()) {
continue;
}
activity.setMinAspectRatio(minAspectRatio);
}
}
/**
* @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
* @param recreateOnConfigChanges The bit mask recreateOnConfigChanges fetched from
@@ -4888,6 +4928,7 @@ public class PackageParser {
info.windowLayout = target.info.windowLayout;
info.resizeMode = target.info.resizeMode;
info.maxAspectRatio = target.info.maxAspectRatio;
info.minAspectRatio = target.info.minAspectRatio;
info.requestedVrComponent = target.info.requestedVrComponent;
info.encryptionAware = info.directBootAware = target.info.directBootAware;
@@ -7773,11 +7814,16 @@ public class PackageParser {
@UnsupportedAppUsage
public final ActivityInfo info;
private boolean mHasMaxAspectRatio;
private boolean mHasMinAspectRatio;
private boolean hasMaxAspectRatio() {
return mHasMaxAspectRatio;
}
private boolean hasMinAspectRatio() {
return mHasMinAspectRatio;
}
// To construct custom activity which does not exist in manifest
Activity(final Package owner, final String className, final ActivityInfo info) {
super(owner, new ArrayList<>(0), className);
@@ -7813,6 +7859,22 @@ public class PackageParser {
mHasMaxAspectRatio = true;
}
private void setMinAspectRatio(float minAspectRatio) {
if (info.resizeMode == RESIZE_MODE_RESIZEABLE
|| info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
// Resizeable activities can be put in any aspect ratio.
return;
}
if (minAspectRatio < 1.0f && minAspectRatio != 0) {
// Ignore any value lesser than 1.0.
return;
}
info.minAspectRatio = minAspectRatio;
mHasMinAspectRatio = true;
}
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("Activity{");
@@ -7833,12 +7895,14 @@ public class PackageParser {
super.writeToParcel(dest, flags);
dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
dest.writeBoolean(mHasMaxAspectRatio);
dest.writeBoolean(mHasMinAspectRatio);
}
private Activity(Parcel in) {
super(in);
info = in.readParcelable(Object.class.getClassLoader());
mHasMaxAspectRatio = in.readBoolean();
mHasMinAspectRatio = in.readBoolean();
for (ActivityIntentInfo aii : intents) {
aii.activity = this;

View File

@@ -1294,6 +1294,20 @@
supports any size. -->
<attr name="maxAspectRatio" format="float" />
<!-- This value indicates the minimum aspect ratio the activity supports. If the app runs on a
device with a narrower aspect ratio, the system automatically letterboxes the app, leaving
portions of the screen unused so the app can run at its specified minimum aspect ratio.
<p>
Minimum aspect ratio, expressed as (longer dimension / shorter dimension) in decimal
form. For example, if the minimum aspect ratio is 4:3, set value to 1.33.
<p>
Value needs to be greater or equal to 1.0, otherwise it is ignored.
<p>
NOTE: This attribute is ignored if the activity has
{@link android.R.attr#resizeableActivity} set to true, since that means your activity
supports any size. -->
<attr name="minAspectRatio" format="float" />
<!-- This value indicates how tasks rooted at this activity will behave in lockTask mode.
While in lockTask mode the system will not launch non-permitted tasks until
lockTask mode is disabled.
@@ -1571,6 +1585,7 @@
<attr name="directBootAware" />
<attr name="resizeableActivity" />
<attr name="maxAspectRatio" />
<attr name="minAspectRatio" />
<attr name="networkSecurityConfig" />
<!-- Declare the category of this app. Categories are used to cluster multiple apps
together into meaningful groups, such as when summarizing battery, network, or
@@ -2386,6 +2401,7 @@
<attr name="resizeableActivity" />
<attr name="supportsPictureInPicture" />
<attr name="maxAspectRatio" />
<attr name="minAspectRatio" />
<attr name="lockTaskMode" />
<attr name="showForAllUsers" />

View File

@@ -2931,6 +2931,7 @@
<public name="selectionDividerHeight" />
<public name="foregroundServiceType" />
<public name="hasFragileUserData" />
<public name="minAspectRatio" />
</public-group>
<public-group type="drawable" first-id="0x010800b4">

View File

@@ -86,6 +86,7 @@ import static android.os.Build.VERSION_CODES.O;
import static android.os.Process.SYSTEM_UID;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
@@ -583,6 +584,9 @@ final class ActivityRecord extends ConfigurationContainer {
if (info.maxAspectRatio != 0) {
pw.println(prefix + "maxAspectRatio=" + info.maxAspectRatio);
}
if (info.minAspectRatio != 0) {
pw.println(prefix + "minAspectRatio=" + info.minAspectRatio);
}
}
}
@@ -2593,7 +2597,10 @@ final class ActivityRecord extends ConfigurationContainer {
outBounds.setEmpty();
final float maxAspectRatio = info.maxAspectRatio;
final ActivityStack stack = getActivityStack();
if (task == null || stack == null || task.inMultiWindowMode() || maxAspectRatio == 0
final float minAspectRatio = info.minAspectRatio;
if (task == null || stack == null || task.inMultiWindowMode()
|| (maxAspectRatio == 0 && minAspectRatio == 0)
|| isInVrUiMode(getConfiguration())) {
// We don't set override configuration if that activity task isn't fullscreen. I.e. the
// activity is in multi-window mode. Or, there isn't a max aspect ratio specified for
@@ -2608,20 +2615,35 @@ final class ActivityRecord extends ConfigurationContainer {
final Rect appBounds = getParent().getWindowConfiguration().getAppBounds();
final int containingAppWidth = appBounds.width();
final int containingAppHeight = appBounds.height();
int maxActivityWidth = containingAppWidth;
int maxActivityHeight = containingAppHeight;
final float containingRatio = Math.max(containingAppWidth, containingAppHeight)
/ (float) Math.min(containingAppWidth, containingAppHeight);
if (containingAppWidth < containingAppHeight) {
// Width is the shorter side, so we use that to figure-out what the max. height
// should be given the aspect ratio.
maxActivityHeight = (int) ((maxActivityWidth * maxAspectRatio) + 0.5f);
} else {
// Height is the shorter side, so we use that to figure-out what the max. width
// should be given the aspect ratio.
maxActivityWidth = (int) ((maxActivityHeight * maxAspectRatio) + 0.5f);
int activityWidth = containingAppWidth;
int activityHeight = containingAppHeight;
if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
if (containingAppWidth < containingAppHeight) {
// Width is the shorter side, so we use that to figure-out what the max. height
// should be given the aspect ratio.
activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
} else {
// Height is the shorter side, so we use that to figure-out what the max. width
// should be given the aspect ratio.
activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
}
} else if (containingRatio < minAspectRatio && minAspectRatio != 0) {
if (containingAppWidth < containingAppHeight) {
// Width is the shorter side, so we use the height to figure-out what the max. width
// should be given the aspect ratio.
activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
} else {
// Height is the shorter side, so we use the width to figure-out what the max.
// height should be given the aspect ratio.
activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
}
}
if (containingAppWidth <= maxActivityWidth && containingAppHeight <= maxActivityHeight) {
if (containingAppWidth <= activityWidth && containingAppHeight <= activityHeight) {
// The display matches or is less than the activity aspect ratio, so nothing else to do.
// Return the existing bounds. If this method is running for the first time,
// {@link #getRequestedOverrideBounds()} will be empty (representing no override). If
@@ -2636,12 +2658,21 @@ final class ActivityRecord extends ConfigurationContainer {
// Also account for the left / top insets (e.g. from display cutouts), which will be clipped
// away later in StackWindowController.adjustConfigurationForBounds(). Otherwise, the app
// bounds would end up too small.
outBounds.set(0, 0, maxActivityWidth + appBounds.left, maxActivityHeight + appBounds.top);
outBounds.set(0, 0, activityWidth + appBounds.left, activityHeight + appBounds.top);
if (mAtmService.mWindowManager.getNavBarPosition(getDisplayId()) == NAV_BAR_LEFT) {
final int navBarPosition = mAtmService.mWindowManager.getNavBarPosition(getDisplayId());
if (navBarPosition == NAV_BAR_LEFT) {
// Position the activity frame on the opposite side of the nav bar.
outBounds.left = appBounds.right - maxActivityWidth;
outBounds.left = appBounds.right - activityWidth;
outBounds.right = appBounds.right;
} else if (navBarPosition == NAV_BAR_RIGHT) {
// Position the activity frame on the opposite side of the nav bar.
outBounds.left = 0;
outBounds.right = activityWidth + appBounds.left;
} else {
// Horizontally center the frame.
outBounds.left = appBounds.left + (containingAppWidth - activityWidth) / 2;
outBounds.right = outBounds.left + activityWidth;
}
}