diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 1e9cddbb684ad..9832bc1b79d23 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -51,7 +51,9 @@ import android.content.pm.dex.ArtManager; import android.content.pm.parsing.PackageInfoWithoutStateUtils; import android.content.pm.parsing.ParsingPackage; import android.content.pm.parsing.ParsingPackageUtils; +import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseResult; +import android.content.pm.parsing.result.ParseTypeImpl; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.graphics.Rect; @@ -6061,7 +6063,8 @@ public abstract class PackageManager { boolean collectCertificates = (flags & PackageManager.GET_SIGNATURES) != 0 || (flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0; - ParseResult result = ParsingPackageUtils.parseDefaultOneTime( + ParseInput input = ParseTypeImpl.forParsingWithoutPlatformCompat().reset(); + ParseResult result = ParsingPackageUtils.parseDefault(input, new File(archiveFilePath), 0, collectCertificates); if (result.isError()) { return null; diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index cb2943122781c..5a7947503d5c7 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -131,14 +131,23 @@ public class ParsingPackageUtils { public static final String TAG = ParsingUtils.TAG; /** - * For cases outside of PackageManagerService when an APK needs to be parsed as a one-off - * request, without caching the input object and without querying the internal system state - * for feature support. + * @see #parseDefault(ParseInput, File, int, boolean) */ @NonNull public static ParseResult parseDefaultOneTime(File file, @PackageParser.ParseFlags int parseFlags, boolean collectCertificates) { ParseInput input = ParseTypeImpl.forDefaultParsing().reset(); + return parseDefault(input, file, parseFlags, collectCertificates); + } + + /** + * For cases outside of PackageManagerService when an APK needs to be parsed as a one-off + * request, without caching the input object and without querying the internal system state + * for feature support. + */ + @NonNull + public static ParseResult parseDefault(ParseInput input, File file, + @PackageParser.ParseFlags int parseFlags, boolean collectCertificates) { ParseResult result; ParsingPackageUtils parser = new ParsingPackageUtils(false, null, null, new Callback() { diff --git a/core/java/android/content/pm/parsing/result/ParseInput.java b/core/java/android/content/pm/parsing/result/ParseInput.java index d5898b7f57a1a..0fb18aee1eb41 100644 --- a/core/java/android/content/pm/parsing/result/ParseInput.java +++ b/core/java/android/content/pm/parsing/result/ParseInput.java @@ -16,6 +16,7 @@ package android.content.pm.parsing.result; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.ChangeId; @@ -69,6 +70,25 @@ public interface ParseInput { @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) public static final long RESOURCES_ARSC_COMPRESSED = 132742131; + + /** + * TODO(chiuwinson): This is required because PackageManager#getPackageArchiveInfo + * cannot read the targetSdk info from the changeId because it requires the + * READ_COMPAT_CHANGE_CONFIG which cannot be obtained automatically without entering the + * server process. This should be removed once an alternative is found, or if the API + * is removed. + * @return the targetSdk that this change is gated on (> check), or -1 if disabled + */ + @IntRange(from = -1, to = Integer.MAX_VALUE) + public static int getTargetSdkForChange(long changeId) { + if (changeId == MISSING_APP_TAG + || changeId == EMPTY_INTENT_ACTION_CATEGORY + || changeId == RESOURCES_ARSC_COMPRESSED) { + return Build.VERSION_CODES.Q; + } + + return -1; + } } ParseResult success(ResultType result); diff --git a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java index 91e571be3d89c..14992fb2a4d16 100644 --- a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java +++ b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java @@ -64,6 +64,21 @@ public class ParseTypeImpl implements ParseInput, ParseResult { private String mPackageName; private Integer mTargetSdkVersion; + /** + * Specifically for {@link PackageManager#getPackageArchiveInfo(String, int)} where + * {@link IPlatformCompat} cannot be used because the cross-package READ_COMPAT_CHANGE_CONFIG + * permission cannot be obtained. + */ + public static ParseTypeImpl forParsingWithoutPlatformCompat() { + return new ParseTypeImpl((changeId, packageName, targetSdkVersion) -> { + int gateSdkVersion = DeferredError.getTargetSdkForChange(changeId); + if (gateSdkVersion == -1) { + return false; + } + return targetSdkVersion > gateSdkVersion; + }); + } + /** * Assumes {@link Context#PLATFORM_COMPAT_SERVICE} is available to the caller. For use * with {@link android.content.pm.parsing.ApkLiteParseUtils} or similar where parsing is