diff --git a/api/current.txt b/api/current.txt index 620aef4855f86..63bbad29cc0ab 100644 --- a/api/current.txt +++ b/api/current.txt @@ -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 diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 0a4f4eb8506ca..0edb36c5daff8 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -235,6 +235,15 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { */ public float maxAspectRatio; + /** + * Value indicating the minimum aspect ratio the activity supports. + *

+ * 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(); } /** diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index c361ac12667ed..0c438afd7a83d 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -712,6 +712,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public float maxAspectRatio; + /** + * Value indicating the minimum aspect ratio the application supports. + *

+ * 0 means unset. + * @see {@link android.R.attr#minAspectRatio}. + * @hide + */ + public float minAspectRatio; + /** @removed */ @Deprecated public String volumeUuid; diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 61a74ded02d07..e38b294b44850 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -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; diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 35263a3fa8919..dd51cb615d8a5 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1294,6 +1294,20 @@ supports any size. --> + + +