From 22571db5a6f2f24720ab33adf920b64a9725e6eb Mon Sep 17 00:00:00 2001 From: Bryce Lee Date: Fri, 7 Jul 2017 15:54:18 -0700 Subject: [PATCH] Allow max aspect ratio to be specified by meta-data tag. This changelist identifies aspect ratios set via meta-data tags on the activity or application and applies them to the proper scope. Values specified via styled attribute take precedence, and values specified by the activity take priority over values in at the application level. Fixes: 63386222 Test: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsAppTestCases android.app.cts.AspectRatioTests Test: go/wm-smoke Change-Id: I0d8d6b2778e7fc12bb9feb85c651e5ec22927f5f --- .../android/content/pm/PackageParser.java | 83 +++++++++++++++---- 1 file changed, 66 insertions(+), 17 deletions(-) diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index c67376c25885a..b39f9a5816fee 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -200,6 +200,8 @@ public class PackageParser { // Temporary workaround; allow meta-data to expose components to instant apps private static final String META_DATA_INSTANT_APPS = "instantapps.clients.allowed"; + private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect"; + /** * Bit mask of all the valid bits that can be set in recreateOnConfigChanges. * @hide @@ -3639,6 +3641,7 @@ public class PackageParser { final int innerDepth = parser.getDepth(); int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { @@ -3815,6 +3818,10 @@ 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); + modifySharedLibrariesForBackwardCompatibility(owner); if (hasDomainURLs(owner)) { @@ -4258,7 +4265,12 @@ public class PackageParser { a.info.flags |= FLAG_ALWAYS_FOCUSABLE; } - setActivityMaxAspectRatio(a.info, sa, owner); + if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio) + && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio) + == TypedValue.TYPE_FLOAT) { + a.setMaxAspectRatio(sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio, + 0 /*default*/)); + } a.info.lockTaskLaunchMode = sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0); @@ -4496,28 +4508,40 @@ public class PackageParser { } } - private void setActivityMaxAspectRatio(ActivityInfo aInfo, TypedArray sa, Package owner) { - if (aInfo.resizeMode == RESIZE_MODE_RESIZEABLE - || aInfo.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) { - // Resizeable activities can be put in any aspect ratio. - aInfo.maxAspectRatio = 0; - return; - } - + /** + * Sets every the max aspect ratio of every child activity that doesn't already have an aspect + * ratio set. + */ + private void setMaxAspectRatio(Package owner) { // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater. // NOTE: 16.7:9 was the max aspect ratio Android devices can support pre-O per the CDD. - float defaultMaxAspectRatio = owner.applicationInfo.targetSdkVersion < O + float maxAspectRatio = owner.applicationInfo.targetSdkVersion < O ? DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0; - if (owner.applicationInfo.maxAspectRatio != 0 ) { + + if (owner.applicationInfo.maxAspectRatio != 0) { // Use the application max aspect ration as default if set. - defaultMaxAspectRatio = owner.applicationInfo.maxAspectRatio; + maxAspectRatio = owner.applicationInfo.maxAspectRatio; + } else if (owner.mAppMetaData != null + && owner.mAppMetaData.containsKey(METADATA_MAX_ASPECT_RATIO)) { + maxAspectRatio = owner.mAppMetaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio); } - aInfo.maxAspectRatio = sa.getFloat( - R.styleable.AndroidManifestActivity_maxAspectRatio, defaultMaxAspectRatio); - if (aInfo.maxAspectRatio < 1.0f && aInfo.maxAspectRatio != 0) { - // Ignore any value lesser than 1.0. - aInfo.maxAspectRatio = 0; + for (Activity activity : owner.activities) { + // If the max aspect ratio for the activity has already been set, skip. + if (activity.hasMaxAspectRatio()) { + continue; + } + + // By default we prefer to use a values defined on the activity directly than values + // defined on the application. We do not check the styled attributes on the activity + // as it would have already been set when we processed the activity. We wait to process + // the meta data here since this method is called at the end of processing the + // application and all meta data is guaranteed. + final float activityAspectRatio = activity.metaData != null + ? activity.metaData.getFloat(METADATA_MAX_ASPECT_RATIO, maxAspectRatio) + : maxAspectRatio; + + activity.setMaxAspectRatio(activityAspectRatio); } } @@ -4658,6 +4682,7 @@ public class PackageParser { info.windowLayout = target.info.windowLayout; info.resizeMode = target.info.resizeMode; info.maxAspectRatio = target.info.maxAspectRatio; + info.encryptionAware = info.directBootAware = target.info.directBootAware; Activity a = new Activity(mParseActivityAliasArgs, info); @@ -6940,6 +6965,11 @@ public class PackageParser { public final static class Activity extends Component implements Parcelable { public final ActivityInfo info; + private boolean mHasMaxAspectRatio; + + private boolean hasMaxAspectRatio() { + return mHasMaxAspectRatio; + } public Activity(final ParseComponentArgs args, final ActivityInfo _info) { super(args, _info); @@ -6952,6 +6982,23 @@ public class PackageParser { info.packageName = packageName; } + + private void setMaxAspectRatio(float maxAspectRatio) { + 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 (maxAspectRatio < 1.0f && maxAspectRatio != 0) { + // Ignore any value lesser than 1.0. + return; + } + + info.maxAspectRatio = maxAspectRatio; + mHasMaxAspectRatio = true; + } + public String toString() { StringBuilder sb = new StringBuilder(128); sb.append("Activity{"); @@ -6971,11 +7018,13 @@ public class PackageParser { public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeParcelable(info, flags | Parcelable.PARCELABLE_ELIDE_DUPLICATES); + dest.writeBoolean(mHasMaxAspectRatio); } private Activity(Parcel in) { super(in); info = in.readParcelable(Object.class.getClassLoader()); + mHasMaxAspectRatio = in.readBoolean(); for (ActivityIntentInfo aii : intents) { aii.activity = this;