Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5570d1e6 authored by Mårten Kongstad's avatar Mårten Kongstad
Browse files

Block installs of incompatible minSdkVersion minor values

Parse the minSdkVersionFull attribute during install time of a package
and abort the installation if the attribute requires a newer version of
Android. This works the same as minSdkVersion, but allows the package
author to refer to a minor version of Android.

This CL only adds a simple check during the install flow. Follow-up CLs
will unify the handling of minSdkVersion and minSdkVersionFull, add
support for other attributes that refer to minor versions, etc.

Bug: 377689343
Test: atest 'android.content.pm.parsing.cts.host.UsesSdkTest#minSdkVersionMinorVersionImplicitlySetTo0' 'android.content.pm.parsing.cts.host.UsesSdkTest#minSdkVersionMinorVersionSetTo0' 'android.content.pm.parsing.cts.host.UsesSdkTest#minSdkVersionMinorVersionSetTo1'
Flag: android.sdk.major_minor_versioning_scheme
Change-Id: Ibf43d4e029079112afea54f70dca135dcf0ccd00
parent 55a6cb5f
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -329,6 +329,36 @@ public class FrameworkParsingPackageUtils {
        }
    }

    /**
     * Check if a package is compatible with this platform with regards to its
     * its minSdkVersionFull.
     *
     * @param minSdkVersionFullString    A string representation of a major.minor version,
     *                                   e.g. "12.34"
     * @param platformMinSdkVersionFull The major and minor version of the platform, i.e. the value
     *                                  of Build.VERSION.SDK_INT_FULL
     * @param input                     A ParseInput object to report success or failure
     */
    public static ParseResult<Void> verifyMinSdkVersionFull(@NonNull String minSdkVersionFullString,
            int platformMinSdkVersionFull, @NonNull ParseInput input) {
        int minSdkVersionFull;
        try {
            minSdkVersionFull = Build.parseFullVersion(minSdkVersionFullString);
        } catch (IllegalStateException e) {
            return input.error(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                    e.getMessage());
        }
        if (minSdkVersionFull <= platformMinSdkVersionFull) {
            return input.success(null);
        }
        return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
                "Requires newer sdk version "
                + Build.fullVersionToString(minSdkVersionFull)
                + " (current version is "
                + Build.fullVersionToString(platformMinSdkVersionFull)
                + ")");
    }

    /**
     * Computes the targetSdkVersion to use at runtime. If the package is not compatible with this
     * platform, populates {@code outError[0]} with an error message.
+16 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_
import static android.os.Build.VERSION_CODES.DONUT;
import static android.os.Build.VERSION_CODES.O;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.sdk.Flags.majorMinorVersioningScheme;

import static com.android.internal.pm.pkg.parsing.ParsingUtils.parseKnownActivityEmbeddingCerts;

@@ -1688,6 +1689,21 @@ public class ParsingPackageUtils {
                    targetCode = minCode;
                }

                if (majorMinorVersioningScheme()) {
                    val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersionFull);
                    if (val != null) {
                        if (val.type == TypedValue.TYPE_STRING && val.string != null) {
                            String minSdkVersionFullString = val.string.toString();
                            ParseResult<Void> minSdkVersionFullResult =
                                    FrameworkParsingPackageUtils.verifyMinSdkVersionFull(
                                        minSdkVersionFullString, Build.VERSION.SDK_INT_FULL, input);
                            if (minSdkVersionFullResult.isError()) {
                                return input.error(minSdkVersionFullResult);
                            }
                        }
                    }
                }

                if (isApkInApex) {
                    val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_maxSdkVersion);
                    if (val != null) {