Allow unknown codenames in target sdk version for APK-in-apexes
This is currently a recurring issue every new Android release as a few of our apps will be targeting new platforms and they also get installed on devices running older SDKs. This change only changes behaviour for APK in apexes. Test: atest com.android.server.pm.parsing.PackageParserLegacyCoreTest Bug: 208239394 Merged-In: If1195c8ec39ac88a605e25dfb1c78d49a5aa3e7c Change-Id: If1195c8ec39ac88a605e25dfb1c78d49a5aa3e7c
This commit is contained in:
parent
5ff11183cc
commit
5ef7d7b777
@ -326,6 +326,7 @@ java_defaults {
|
||||
"av-types-aidl-java",
|
||||
"tv_tuner_resource_manager_aidl_interface-java",
|
||||
"soundtrigger_middleware-aidl-java",
|
||||
"modules-utils-build",
|
||||
"modules-utils-preconditions",
|
||||
"modules-utils-synchronous-result-receiver",
|
||||
"modules-utils-os",
|
||||
|
@ -568,7 +568,8 @@ public class ApkLiteParseUtils {
|
||||
}
|
||||
|
||||
ParseResult<Integer> targetResult = FrameworkParsingPackageUtils.computeTargetSdkVersion(
|
||||
targetVer, targetCode, SDK_CODENAMES, input);
|
||||
targetVer, targetCode, SDK_CODENAMES, input,
|
||||
/* allowUnknownCodenames= */ false);
|
||||
if (targetResult.isError()) {
|
||||
return input.error(targetResult);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import android.util.Slog;
|
||||
import android.util.apk.ApkSignatureVerifier;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.modules.utils.build.UnboundedSdkLevel;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@ -334,8 +335,9 @@ public class FrameworkParsingPackageUtils {
|
||||
* If {@code targetCode} is not specified, e.g. the value is {@code null}, then the {@code
|
||||
* targetVers} will be returned unmodified.
|
||||
* <p>
|
||||
* Otherwise, the behavior varies based on whether the current platform is a pre-release
|
||||
* version, e.g. the {@code platformSdkCodenames} array has length > 0:
|
||||
* When {@code allowUnknownCodenames} is false, the behavior varies based on whether the
|
||||
* current platform is a pre-release version, e.g. the {@code platformSdkCodenames} array has
|
||||
* length > 0:
|
||||
* <ul>
|
||||
* <li>If this is a pre-release platform and the value specified by
|
||||
* {@code targetCode} is contained within the array of allowed pre-release
|
||||
@ -343,22 +345,32 @@ public class FrameworkParsingPackageUtils {
|
||||
* <li>If this is a released platform, this method will return -1 to
|
||||
* indicate that the package is not compatible with this platform.
|
||||
* </ul>
|
||||
* <p>
|
||||
* When {@code allowUnknownCodenames} is true, any codename that is not known (presumed to be
|
||||
* a codename announced after the build of the current device) is allowed and this method will
|
||||
* return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
|
||||
*
|
||||
* @param targetVers targetSdkVersion number, if specified in the application
|
||||
* manifest, or 0 otherwise
|
||||
* @param targetCode targetSdkVersion code, if specified in the application manifest,
|
||||
* or {@code null} otherwise
|
||||
* @param platformSdkCodenames array of allowed pre-release SDK codenames for this platform
|
||||
* @param targetVers targetSdkVersion number, if specified in the application
|
||||
* manifest, or 0 otherwise
|
||||
* @param targetCode targetSdkVersion code, if specified in the application manifest,
|
||||
* or {@code null} otherwise
|
||||
* @param platformSdkCodenames array of allowed pre-release SDK codenames for this platform
|
||||
* @param allowUnknownCodenames allow unknown codenames, if true this method will accept unknown
|
||||
* (presumed to be future) codenames
|
||||
* @return the targetSdkVersion to use at runtime if successful
|
||||
*/
|
||||
public static ParseResult<Integer> computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
|
||||
@Nullable String targetCode, @NonNull String[] platformSdkCodenames,
|
||||
@NonNull ParseInput input) {
|
||||
@NonNull ParseInput input, boolean allowUnknownCodenames) {
|
||||
// If it's a release SDK, return the version number unmodified.
|
||||
if (targetCode == null) {
|
||||
return input.success(targetVers);
|
||||
}
|
||||
|
||||
if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
|
||||
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
|
||||
}
|
||||
|
||||
// If it's a pre-release SDK and the codename matches this platform, it
|
||||
// definitely targets this SDK.
|
||||
if (matchTargetCode(platformSdkCodenames, targetCode)) {
|
||||
|
@ -5,3 +5,6 @@ rule android.hidl.** android.internal.hidl.@1
|
||||
# Framework-specific renames.
|
||||
rule android.net.wifi.WifiAnnotations* android.internal.wifi.WifiAnnotations@1
|
||||
rule com.android.server.vcn.util.** com.android.server.vcn.repackaged.util.@1
|
||||
|
||||
# for modules-utils-build dependency
|
||||
rule com.android.modules.utils.build.** android.internal.modules.utils.build.@1
|
||||
|
@ -30,7 +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 static com.android.server.pm.pkg.parsing.ParsingPackageUtils.PARSE_APK_IN_APEX;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@ -359,7 +359,7 @@ final class InitAppsHelper {
|
||||
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;
|
||||
parseFlags |= PARSE_APK_IN_APEX;
|
||||
}
|
||||
mInstallPackageHelper.installPackagesFromDir(scanDir, frameworkSplits, parseFlags,
|
||||
scanFlags, packageParser, executorService);
|
||||
|
@ -209,8 +209,6 @@ 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;
|
||||
@ -238,7 +236,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_APK_IN_APEX = 1 << 9;
|
||||
|
||||
public static final int PARSE_CHATTY = 1 << 31;
|
||||
|
||||
@ -1534,7 +1532,7 @@ public class ParsingPackageUtils {
|
||||
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;
|
||||
final boolean isApkInApex = (flags & PARSE_APK_IN_APEX) != 0;
|
||||
TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk);
|
||||
try {
|
||||
int minVers = ParsingUtils.DEFAULT_MIN_SDK_VERSION;
|
||||
@ -1569,7 +1567,7 @@ public class ParsingPackageUtils {
|
||||
targetCode = minCode;
|
||||
}
|
||||
|
||||
if (checkMaxSdkVersion) {
|
||||
if (isApkInApex) {
|
||||
val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_maxSdkVersion);
|
||||
if (val != null) {
|
||||
// maxSdkVersion only supports integer
|
||||
@ -1578,7 +1576,8 @@ public class ParsingPackageUtils {
|
||||
}
|
||||
|
||||
ParseResult<Integer> targetSdkVersionResult = FrameworkParsingPackageUtils
|
||||
.computeTargetSdkVersion(targetVers, targetCode, SDK_CODENAMES, input);
|
||||
.computeTargetSdkVersion(targetVers, targetCode, SDK_CODENAMES, input,
|
||||
isApkInApex);
|
||||
if (targetSdkVersionResult.isError()) {
|
||||
return input.error(targetSdkVersionResult);
|
||||
}
|
||||
@ -1601,7 +1600,7 @@ public class ParsingPackageUtils {
|
||||
|
||||
pkg.setMinSdkVersion(minSdkVersion)
|
||||
.setTargetSdkVersion(targetSdkVersion);
|
||||
if (checkMaxSdkVersion) {
|
||||
if (isApkInApex) {
|
||||
ParseResult<Integer> maxSdkVersionResult = FrameworkParsingPackageUtils
|
||||
.computeMaxSdkVersion(maxVers, SDK_VERSION, input);
|
||||
if (maxSdkVersionResult.isError()) {
|
||||
|
@ -84,15 +84,15 @@ import java.util.function.Function;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class PackageParserLegacyCoreTest {
|
||||
private static final String RELEASED = null;
|
||||
private static final String OLDER_PRE_RELEASE = "A";
|
||||
private static final String PRE_RELEASE = "B";
|
||||
private static final String NEWER_PRE_RELEASE = "C";
|
||||
private static final String OLDER_PRE_RELEASE = "Q";
|
||||
private static final String PRE_RELEASE = "R";
|
||||
private static final String NEWER_PRE_RELEASE = "Z";
|
||||
|
||||
// Codenames with a fingerprint attached to them. These may only be present in the apps
|
||||
// declared min SDK and not as platform codenames.
|
||||
private static final String OLDER_PRE_RELEASE_WITH_FINGERPRINT = "A.fingerprint";
|
||||
private static final String PRE_RELEASE_WITH_FINGERPRINT = "B.fingerprint";
|
||||
private static final String NEWER_PRE_RELEASE_WITH_FINGERPRINT = "C.fingerprint";
|
||||
private static final String OLDER_PRE_RELEASE_WITH_FINGERPRINT = "Q.fingerprint";
|
||||
private static final String PRE_RELEASE_WITH_FINGERPRINT = "R.fingerprint";
|
||||
private static final String NEWER_PRE_RELEASE_WITH_FINGERPRINT = "Z.fingerprint";
|
||||
|
||||
private static final String[] CODENAMES_RELEASED = { /* empty */};
|
||||
private static final String[] CODENAMES_PRE_RELEASE = {PRE_RELEASE};
|
||||
@ -199,13 +199,14 @@ public class PackageParserLegacyCoreTest {
|
||||
}
|
||||
|
||||
private void verifyComputeTargetSdkVersion(int targetSdkVersion, String targetSdkCodename,
|
||||
boolean isPlatformReleased, int expectedTargetSdk) {
|
||||
boolean isPlatformReleased, boolean allowUnknownCodenames, int expectedTargetSdk) {
|
||||
final ParseTypeImpl input = ParseTypeImpl.forParsingWithoutPlatformCompat();
|
||||
final ParseResult<Integer> result = FrameworkParsingPackageUtils.computeTargetSdkVersion(
|
||||
targetSdkVersion,
|
||||
targetSdkCodename,
|
||||
isPlatformReleased ? CODENAMES_RELEASED : CODENAMES_PRE_RELEASE,
|
||||
input);
|
||||
input,
|
||||
allowUnknownCodenames);
|
||||
|
||||
if (expectedTargetSdk == -1) {
|
||||
assertTrue(result.isError());
|
||||
@ -220,40 +221,61 @@ public class PackageParserLegacyCoreTest {
|
||||
// Do allow older release targetSdkVersion on pre-release platform.
|
||||
// APP: Released API 10
|
||||
// DEV: Pre-release API 20
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, false, OLDER_VERSION);
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, false, false, OLDER_VERSION);
|
||||
|
||||
// Do allow same release targetSdkVersion on pre-release platform.
|
||||
// APP: Released API 20
|
||||
// DEV: Pre-release API 20
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, false, PLATFORM_VERSION);
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, false, false, PLATFORM_VERSION);
|
||||
|
||||
// Do allow newer release targetSdkVersion on pre-release platform.
|
||||
// APP: Released API 30
|
||||
// DEV: Pre-release API 20
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, false, NEWER_VERSION);
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, false, false, NEWER_VERSION);
|
||||
|
||||
// Don't allow older pre-release targetSdkVersion on pre-release platform.
|
||||
// APP: Pre-release API 10
|
||||
// DEV: Pre-release API 20
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, -1);
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false, false, -1);
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false,
|
||||
false, -1
|
||||
);
|
||||
|
||||
// Don't allow older pre-release targetSdkVersion on pre-release platform when
|
||||
// allowUnknownCodenames is true.
|
||||
// APP: Pre-release API 10
|
||||
// DEV: Pre-release API 20
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, false,
|
||||
true, -1);
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, false,
|
||||
true, -1);
|
||||
|
||||
// Do allow same pre-release targetSdkVersion on pre-release platform,
|
||||
// but overwrite the specified version with CUR_DEVELOPMENT.
|
||||
// APP: Pre-release API 20
|
||||
// DEV: Pre-release API 20
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, false,
|
||||
Build.VERSION_CODES.CUR_DEVELOPMENT);
|
||||
false, Build.VERSION_CODES.CUR_DEVELOPMENT);
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, false,
|
||||
Build.VERSION_CODES.CUR_DEVELOPMENT);
|
||||
|
||||
false, Build.VERSION_CODES.CUR_DEVELOPMENT);
|
||||
|
||||
// Don't allow newer pre-release targetSdkVersion on pre-release platform.
|
||||
// APP: Pre-release API 30
|
||||
// DEV: Pre-release API 20
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, -1);
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false, -1);
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false, false, -1);
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false,
|
||||
false, -1
|
||||
);
|
||||
|
||||
// Do allow newer pre-release targetSdkVersion on pre-release platform when
|
||||
// allowUnknownCodenames is true.
|
||||
// APP: Pre-release API 30
|
||||
// DEV: Pre-release API 20
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, false,
|
||||
true, Build.VERSION_CODES.CUR_DEVELOPMENT);
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, false,
|
||||
true, Build.VERSION_CODES.CUR_DEVELOPMENT);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -261,36 +283,58 @@ public class PackageParserLegacyCoreTest {
|
||||
// Do allow older release targetSdkVersion on released platform.
|
||||
// APP: Released API 10
|
||||
// DEV: Released API 20
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, true, OLDER_VERSION);
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, RELEASED, true, false, OLDER_VERSION);
|
||||
|
||||
// Do allow same release targetSdkVersion on released platform.
|
||||
// APP: Released API 20
|
||||
// DEV: Released API 20
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, true, PLATFORM_VERSION);
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, RELEASED, true, false, PLATFORM_VERSION);
|
||||
|
||||
// Do allow newer release targetSdkVersion on released platform.
|
||||
// APP: Released API 30
|
||||
// DEV: Released API 20
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, true, NEWER_VERSION);
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, RELEASED, true, false, NEWER_VERSION);
|
||||
|
||||
// Don't allow older pre-release targetSdkVersion on released platform.
|
||||
// APP: Pre-release API 10
|
||||
// DEV: Released API 20
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, -1);
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE, true, false, -1);
|
||||
verifyComputeTargetSdkVersion(OLDER_VERSION, OLDER_PRE_RELEASE_WITH_FINGERPRINT, true,
|
||||
false, -1
|
||||
);
|
||||
|
||||
// Don't allow same pre-release targetSdkVersion on released platform.
|
||||
// APP: Pre-release API 20
|
||||
// DEV: Released API 20
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, -1);
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, -1);
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, false, -1);
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, false,
|
||||
-1
|
||||
);
|
||||
|
||||
// Don't allow same pre-release targetSdkVersion on released platform when
|
||||
// allowUnknownCodenames is true.
|
||||
// APP: Pre-release API 20
|
||||
// DEV: Released API 20
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE, true, true,
|
||||
-1);
|
||||
verifyComputeTargetSdkVersion(PLATFORM_VERSION, PRE_RELEASE_WITH_FINGERPRINT, true, true,
|
||||
-1);
|
||||
|
||||
// Don't allow newer pre-release targetSdkVersion on released platform.
|
||||
// APP: Pre-release API 30
|
||||
// DEV: Released API 20
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1);
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true, -1);
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, false, -1);
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true,
|
||||
false, -1
|
||||
);
|
||||
// Do allow newer pre-release targetSdkVersion on released platform when
|
||||
// allowUnknownCodenames is true.
|
||||
// APP: Pre-release API 30
|
||||
// DEV: Released API 20
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, true,
|
||||
Build.VERSION_CODES.CUR_DEVELOPMENT);
|
||||
verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE_WITH_FINGERPRINT, true,
|
||||
true, Build.VERSION_CODES.CUR_DEVELOPMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user