diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java index 8b86a16075e9d..a65b6815f8adc 100644 --- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java @@ -378,6 +378,30 @@ public class FrameworkParsingPackageUtils { } } + /** + * Computes the maxSdkVersion. If the package is not compatible with this platform, populates + * {@code outError[0]} with an error message. + *

+ * {@code maxVers} is compared against {@code platformSdkVersion}. If {@code maxVers} is less + * than the {@code platformSdkVersion} then populates {@code outError[0]} with an error message. + * Otherwise, it returns {@code maxVers} unmodified. + * + * @param maxVers maxSdkVersion number, if specified in the application manifest, or {@code + * Integer.MAX_VALUE} otherwise + * @param platformSdkVersion platform SDK version number, typically Build.VERSION.SDK_INT + * @return the maxSdkVersion that was recognised or an error if the condition is not satisfied + */ + public static ParseResult computeMaxSdkVersion(@IntRange(from = 0) int maxVers, + @IntRange(from = 1) int platformSdkVersion, @NonNull ParseInput input) { + if (platformSdkVersion > maxVers) { + return input.error(PackageManager.INSTALL_FAILED_NEWER_SDK, + "Requires max SDK version " + maxVers + " but is " + + platformSdkVersion); + } else { + return input.success(maxVers); + } + } + /** * Matches a given {@code targetCode} against a set of release codeNames. Target codes can * either be of the form {@code [codename]}" (e.g {@code "Q"}) or of the form {@code diff --git a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java index 6dbe9b6f89f68..8d7762410b274 100644 --- a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java +++ b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java @@ -30,6 +30,7 @@ import static com.android.server.pm.PackageManagerService.SCAN_NO_DEX; import static com.android.server.pm.PackageManagerService.SCAN_REQUIRE_KNOWN; import static com.android.server.pm.PackageManagerService.SYSTEM_PARTITIONS; import static com.android.server.pm.PackageManagerService.TAG; +import static com.android.server.pm.pkg.parsing.ParsingPackageUtils.PARSE_CHECK_MAX_SDK_VERSION; import android.annotation.Nullable; import android.content.pm.parsing.ApkLiteParseUtils; @@ -313,10 +314,14 @@ final class InitAndSystemPackageHelper { @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) private void scanDirTracedLI(File scanDir, List frameworkSplits, - final int parseFlags, int scanFlags, + int parseFlags, int scanFlags, long currentTime, PackageParser2 packageParser, ExecutorService executorService) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]"); try { + if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) { + // when scanning apk in apexes, we want to check the maxSdkVersion + parseFlags |= PARSE_CHECK_MAX_SDK_VERSION; + } mInstallPackageHelper.installPackagesFromDir(scanDir, frameworkSplits, parseFlags, scanFlags, currentTime, packageParser, executorService); } finally { diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java index f6f9faf98c40a..3893f919c26b0 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java @@ -305,6 +305,8 @@ public interface ParsingPackage extends ParsingPackageRead { ParsingPackage setMinSdkVersion(int minSdkVersion); + ParsingPackage setMaxSdkVersion(int maxSdkVersion); + ParsingPackage setNetworkSecurityConfigRes(int networkSecurityConfigRes); ParsingPackage setNonLocalizedLabel(CharSequence nonLocalizedLabel); diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java index 67670272ef8b0..ca7282847197b 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageImpl.java @@ -383,6 +383,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, @Nullable private SparseIntArray minExtensionVersions; private int minSdkVersion = ParsingUtils.DEFAULT_MIN_SDK_VERSION; + private int maxSdkVersion = ParsingUtils.DEFAULT_MAX_SDK_VERSION; private int networkSecurityConfigRes; @Nullable private CharSequence nonLocalizedLabel; @@ -1308,6 +1309,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, dest.writeFloat(this.maxAspectRatio); dest.writeFloat(this.minAspectRatio); dest.writeInt(this.minSdkVersion); + dest.writeInt(this.maxSdkVersion); dest.writeInt(this.networkSecurityConfigRes); dest.writeCharSequence(this.nonLocalizedLabel); dest.writeString(this.permission); @@ -1456,6 +1458,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, this.maxAspectRatio = in.readFloat(); this.minAspectRatio = in.readFloat(); this.minSdkVersion = in.readInt(); + this.maxSdkVersion = in.readInt(); this.networkSecurityConfigRes = in.readInt(); this.nonLocalizedLabel = in.readCharSequence(); this.permission = in.readString(); @@ -2069,6 +2072,11 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, return minSdkVersion; } + @Override + public int getMaxSdkVersion() { + return maxSdkVersion; + } + @Override public int getNetworkSecurityConfigRes() { return networkSecurityConfigRes; @@ -2603,6 +2611,12 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden, return this; } + @Override + public ParsingPackageImpl setMaxSdkVersion(int value) { + maxSdkVersion = value; + return this; + } + @Override public ParsingPackageImpl setNetworkSecurityConfigRes(int value) { networkSecurityConfigRes = value; diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java index 3eaca9dddcc41..f51ac263a97cc 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java @@ -209,6 +209,8 @@ public class ParsingPackageUtils { public static final int SDK_VERSION = Build.VERSION.SDK_INT; public static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES; + public static final String[] PREVIOUS_CODENAMES = + Build.VERSION.KNOWN_CODENAMES.toArray(new String[]{}); public static boolean sCompatibilityModeEnabled = true; public static boolean sUseRoundIcon = false; @@ -236,6 +238,7 @@ public class ParsingPackageUtils { */ public static final int PARSE_IGNORE_OVERLAY_REQUIRED_SYSTEM_PROPERTY = 1 << 7; public static final int PARSE_FRAMEWORK_RES_SPLITS = 1 << 8; + public static final int PARSE_CHECK_MAX_SDK_VERSION = 1 << 9; public static final int PARSE_CHATTY = 1 << 31; @@ -1004,7 +1007,7 @@ public class ParsingPackageUtils { case TAG_FEATURE_GROUP: return parseFeatureGroup(input, pkg, res, parser); case TAG_USES_SDK: - return parseUsesSdk(input, pkg, res, parser); + return parseUsesSdk(input, pkg, res, parser, flags); case TAG_SUPPORT_SCREENS: return parseSupportScreens(input, pkg, res, parser); case TAG_PROTECTED_BROADCAST: @@ -1516,15 +1519,17 @@ public class ParsingPackageUtils { } private static ParseResult parseUsesSdk(ParseInput input, - ParsingPackage pkg, Resources res, XmlResourceParser parser) + ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags) throws IOException, XmlPullParserException { if (SDK_VERSION > 0) { + final boolean checkMaxSdkVersion = (flags & PARSE_CHECK_MAX_SDK_VERSION) != 0; TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk); try { int minVers = ParsingUtils.DEFAULT_MIN_SDK_VERSION; String minCode = null; int targetVers = ParsingUtils.DEFAULT_TARGET_SDK_VERSION; String targetCode = null; + int maxVers = Integer.MAX_VALUE; TypedValue val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersion); if (val != null) { @@ -1552,6 +1557,14 @@ public class ParsingPackageUtils { targetCode = minCode; } + if (checkMaxSdkVersion) { + val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_maxSdkVersion); + if (val != null) { + // maxSdkVersion only supports integer + maxVers = val.data; + } + } + ParseResult targetSdkVersionResult = FrameworkParsingPackageUtils .computeTargetSdkVersion(targetVers, targetCode, SDK_CODENAMES, input); if (targetSdkVersionResult.isError()) { @@ -1576,6 +1589,15 @@ public class ParsingPackageUtils { pkg.setMinSdkVersion(minSdkVersion) .setTargetSdkVersion(targetSdkVersion); + if (checkMaxSdkVersion) { + ParseResult maxSdkVersionResult = FrameworkParsingPackageUtils + .computeMaxSdkVersion(maxVers, SDK_VERSION, input); + if (maxSdkVersionResult.isError()) { + return input.error(maxSdkVersionResult); + } + int maxSdkVersion = maxSdkVersionResult.getResult(); + pkg.setMaxSdkVersion(maxSdkVersion); + } int type; final int innerDepth = parser.getDepth(); diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java index cb474df8b4690..07512855d2767 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingUtils.java @@ -50,6 +50,7 @@ public class ParsingUtils { public static final String ANDROID_RES_NAMESPACE = "http://schemas.android.com/apk/res/android"; public static final int DEFAULT_MIN_SDK_VERSION = 1; + public static final int DEFAULT_MAX_SDK_VERSION = Integer.MAX_VALUE; public static final int DEFAULT_TARGET_SDK_VERSION = 0; public static final int NOT_SET = -1; diff --git a/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java b/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java index 3205b76d6dadf..99bcdb964c2f4 100644 --- a/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java +++ b/services/core/java/com/android/server/pm/pkg/parsing/PkgWithoutStateAppInfo.java @@ -249,6 +249,11 @@ public interface PkgWithoutStateAppInfo { */ int getMinSdkVersion(); + /** + * @see R.styleable#AndroidManifestUsesSdk_maxSdkVersion + */ + int getMaxSdkVersion(); + /** * @see ApplicationInfo#getNativeHeapZeroInitialized() * @see R.styleable#AndroidManifestApplication_nativeHeapZeroInitialized