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

Commit a83fad74 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Migrate remaining parsePackage V1 to V2" into rvc-dev

parents df554bb5 3cb5610a
Loading
Loading
Loading
Loading
+19 −20
Original line number Diff line number Diff line
@@ -47,8 +47,11 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.PackageParser.PackageParserException;
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.ParseResult;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.Rect;
@@ -6037,28 +6040,24 @@ public abstract class PackageManager {
    @Nullable
    public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath,
            @PackageInfoFlags int flags) {
        final PackageParser parser = new PackageParser();
        parser.setCallback(new PackageParser.CallbackImpl(this));
        final File apkFile = new File(archiveFilePath);
        try {
            if ((flags & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) {
                // Caller expressed an explicit opinion about what encryption
                // aware/unaware components they want to see, so fall through and
                // give them what they want
            } else {
                // Caller expressed no opinion, so match everything
                flags |= MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
        if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                | PackageManager.MATCH_DIRECT_BOOT_AWARE)) == 0) {
            // Caller expressed no opinion about what encryption
            // aware/unaware components they want to see, so match both
            flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
        }

            PackageParser.Package pkg = parser.parseMonolithicPackage(apkFile, 0);
            if ((flags & GET_SIGNATURES) != 0) {
                PackageParser.collectCertificates(pkg, false /* skipVerify */);
            }
            PackageUserState state = new PackageUserState();
            return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, state);
        } catch (PackageParserException e) {
        boolean collectCertificates = (flags & PackageManager.GET_SIGNATURES) != 0
                || (flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0;

        ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefaultOneTime(
                new File(archiveFilePath), 0, collectCertificates);
        if (result.isError()) {
            return null;
        }
        return PackageInfoWithoutStateUtils.generate(result.getResult(), null, flags, 0, 0, null,
                new PackageUserState(), UserHandle.getCallingUserId());
    }

    /**
+4 −0
Original line number Diff line number Diff line
@@ -1517,6 +1517,10 @@ public class PackageParser {
                ? null : "must have at least one '.' separator";
    }

    /**
     * @deprecated Use {@link android.content.pm.parsing.ApkLiteParseUtils#parsePackageSplitNames}
     */
    @Deprecated
    public static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
            AttributeSet attrs) throws IOException, XmlPullParserException,
            PackageParserException {
+143 −79
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.content.pm.parsing;

import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;

import android.compat.annotation.UnsupportedAppUsage;
@@ -23,6 +25,8 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.VerifierInfo;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
import android.content.res.ApkAssets;
import android.content.res.XmlResourceParser;
import android.os.Trace;
@@ -70,47 +74,60 @@ public class ApkLiteParseUtils {
     *
     * @see PackageParser#parsePackage(File, int)
     */
    @UnsupportedAppUsage
    public static PackageParser.PackageLite parsePackageLite(File packageFile, int flags)
            throws PackageParser.PackageParserException {
    public static ParseResult<PackageParser.PackageLite> parsePackageLite(ParseInput input,
            File packageFile, int flags) {
        if (packageFile.isDirectory()) {
            return parseClusterPackageLite(packageFile, flags);
            return parseClusterPackageLite(input, packageFile, flags);
        } else {
            return parseMonolithicPackageLite(packageFile, flags);
            return parseMonolithicPackageLite(input, packageFile, flags);
        }
    }

    public static PackageParser.PackageLite parseMonolithicPackageLite(File packageFile, int flags)
            throws PackageParser.PackageParserException {
    public static ParseResult<PackageParser.PackageLite> parseMonolithicPackageLite(
            ParseInput input, File packageFile, int flags) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
        final PackageParser.ApkLite baseApk = parseApkLite(packageFile, flags);
        try {
            ParseResult<PackageParser.ApkLite> result = parseApkLite(input, packageFile, flags);
            if (result.isError()) {
                return input.error(result);
            }

            final PackageParser.ApkLite baseApk = result.getResult();
            final String packagePath = packageFile.getAbsolutePath();
            return input.success(
                    new PackageParser.PackageLite(packagePath, baseApk, null, null, null, null,
                            null, null));
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        return new PackageParser.PackageLite(packagePath, baseApk, null, null, null, null,
                null, null);
        }
    }

    public static PackageParser.PackageLite parseClusterPackageLite(File packageDir, int flags)
            throws PackageParser.PackageParserException {
    public static ParseResult<PackageParser.PackageLite> parseClusterPackageLite(ParseInput input,
            File packageDir, int flags) {
        final File[] files = packageDir.listFiles();
        if (ArrayUtils.isEmpty(files)) {
            throw new PackageParser.PackageParserException(
                    PackageManager.INSTALL_PARSE_FAILED_NOT_APK, "No packages found in split");
            return input.error(PackageManager.INSTALL_PARSE_FAILED_NOT_APK,
                    "No packages found in split");
        }
        // Apk directory is directly nested under the current directory
        if (files.length == 1 && files[0].isDirectory()) {
            return parseClusterPackageLite(files[0], flags);
            return parseClusterPackageLite(input, files[0], flags);
        }

        String packageName = null;
        int versionCode = 0;

        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
        final ArrayMap<String, PackageParser.ApkLite> apks = new ArrayMap<>();
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
        try {
            for (File file : files) {
                if (PackageParser.isApkFile(file)) {
                final PackageParser.ApkLite lite = parseApkLite(file, flags);
                    ParseResult<PackageParser.ApkLite> result = parseApkLite(input, file, flags);
                    if (result.isError()) {
                        return input.error(result);
                    }

                    final PackageParser.ApkLite lite = result.getResult();
                    // Assert that all package names and version codes are
                    // consistent with the first one we encounter.
                    if (packageName == null) {
@@ -118,14 +135,12 @@ public class ApkLiteParseUtils {
                        versionCode = lite.versionCode;
                    } else {
                        if (!packageName.equals(lite.packageName)) {
                        throw new PackageParser.PackageParserException(
                                PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
                            return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
                                    "Inconsistent package " + lite.packageName + " in " + file
                                            + "; expected " + packageName);
                        }
                        if (versionCode != lite.versionCode) {
                        throw new PackageParser.PackageParserException(
                                PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
                            return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
                                    "Inconsistent version " + lite.versionCode + " in " + file
                                            + "; expected " + versionCode);
                        }
@@ -133,19 +148,19 @@ public class ApkLiteParseUtils {

                    // Assert that each split is defined only oncuses-static-libe
                    if (apks.put(lite.splitName, lite) != null) {
                    throw new PackageParser.PackageParserException(
                            PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
                        return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
                                "Split name " + lite.splitName
                                        + " defined more than once; most recent was " + file);
                    }
                }
            }
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }

        final PackageParser.ApkLite baseApk = apks.remove(null);
        if (baseApk == null) {
            throw new PackageParser.PackageParserException(
                    PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
            return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST,
                    "Missing base APK in " + packageDir);
        }

@@ -180,8 +195,9 @@ public class ApkLiteParseUtils {
        }

        final String codePath = packageDir.getAbsolutePath();
        return new PackageParser.PackageLite(codePath, baseApk, splitNames, isFeatureSplits,
                usesSplitNames, configForSplits, splitCodePaths, splitRevisionCodes);
        return input.success(new PackageParser.PackageLite(codePath, baseApk, splitNames,
                isFeatureSplits, usesSplitNames, configForSplits, splitCodePaths,
                splitRevisionCodes));
    }

    /**
@@ -192,9 +208,9 @@ public class ApkLiteParseUtils {
     * @param flags optional parse flags, such as
     *            {@link PackageParser#PARSE_COLLECT_CERTIFICATES}
     */
    public static PackageParser.ApkLite parseApkLite(File apkFile, int flags)
            throws PackageParser.PackageParserException {
        return parseApkLiteInner(apkFile, null, null, flags);
    public static ParseResult<PackageParser.ApkLite> parseApkLite(ParseInput input, File apkFile,
            int flags) {
        return parseApkLiteInner(input, apkFile, null, null, flags);
    }

    /**
@@ -206,13 +222,13 @@ public class ApkLiteParseUtils {
     * @param flags optional parse flags, such as
     *            {@link PackageParser#PARSE_COLLECT_CERTIFICATES}
     */
    public static PackageParser.ApkLite parseApkLite(FileDescriptor fd, String debugPathName,
            int flags) throws PackageParser.PackageParserException {
        return parseApkLiteInner(null, fd, debugPathName, flags);
    public static ParseResult<PackageParser.ApkLite> parseApkLite(ParseInput input,
            FileDescriptor fd, String debugPathName, int flags) {
        return parseApkLiteInner(input, null, fd, debugPathName, flags);
    }

    private static PackageParser.ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd,
            String debugPathName, int flags) throws PackageParser.PackageParserException {
    private static ParseResult<PackageParser.ApkLite> parseApkLiteInner(ParseInput input,
            File apkFile, FileDescriptor fd, String debugPathName, int flags) {
        final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();

        XmlResourceParser parser = null;
@@ -223,8 +239,7 @@ public class ApkLiteParseUtils {
                        ? ApkAssets.loadFromFd(fd, debugPathName, 0 /* flags */, null /* assets */)
                        : ApkAssets.loadFromPath(apkPath);
            } catch (IOException e) {
                throw new PackageParser.PackageParserException(
                        PackageManager.INSTALL_PARSE_FAILED_NOT_APK,
                return input.error(PackageManager.INSTALL_PARSE_FAILED_NOT_APK,
                        "Failed to parse " + apkPath, e);
            }

@@ -235,9 +250,15 @@ public class ApkLiteParseUtils {
                final boolean skipVerify = (flags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0;
                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
                try {
                    signingDetails = ParsingPackageUtils.collectCertificates(apkFile.getAbsolutePath(),
                            skipVerify, false, PackageParser.SigningDetails.UNKNOWN,
                    ParseResult<PackageParser.SigningDetails> result =
                            ParsingPackageUtils.getSigningDetails(input,
                                    apkFile.getAbsolutePath(), skipVerify, false,
                                    PackageParser.SigningDetails.UNKNOWN,
                                    DEFAULT_TARGET_SDK_VERSION);
                    if (result.isError()) {
                        return input.error(result);
                    }
                    signingDetails = result.getResult();
                } finally {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
@@ -246,12 +267,10 @@ public class ApkLiteParseUtils {
            }

            final AttributeSet attrs = parser;
            return parseApkLite(apkPath, parser, attrs, signingDetails);

            return parseApkLite(input, apkPath, parser, attrs, signingDetails);
        } catch (XmlPullParserException | IOException | RuntimeException e) {
            Slog.w(TAG, "Failed to parse " + apkPath, e);
            throw new PackageParser.PackageParserException(
                    PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
            return input.error(PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                    "Failed to parse " + apkPath, e);
        } finally {
            IoUtils.closeQuietly(parser);
@@ -265,12 +284,16 @@ public class ApkLiteParseUtils {
        }
    }

    private static PackageParser.ApkLite parseApkLite(
    private static ParseResult<PackageParser.ApkLite> parseApkLite(ParseInput input,
            String codePath, XmlPullParser parser, AttributeSet attrs,
            PackageParser.SigningDetails signingDetails)
            throws IOException, XmlPullParserException, PackageParser.PackageParserException {
        final Pair<String, String> packageSplit = PackageParser.parsePackageSplitNames(
                parser, attrs);
            throws IOException, XmlPullParserException {
        ParseResult<Pair<String, String>> result = parsePackageSplitNames(input, parser, attrs);
        if (result.isError()) {
            return input.error(result);
        }

        Pair<String, String> packageSplit = result.getResult();

        int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
        int versionCode = 0;
@@ -394,8 +417,7 @@ public class ApkLiteParseUtils {

                usesSplitName = attrs.getAttributeValue(PackageParser.ANDROID_RESOURCES, "name");
                if (usesSplitName == null) {
                    throw new PackageParser.PackageParserException(
                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                    return input.error(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                            "<uses-split> tag requires 'android:name' attribute");
                }
            } else if (PackageParser.TAG_USES_SDK.equals(parser.getName())) {
@@ -423,12 +445,54 @@ public class ApkLiteParseUtils {
            overlayPriority = 0;
        }

        return new PackageParser.ApkLite(codePath, packageSplit.first, packageSplit.second,
                isFeatureSplit, configForSplit, usesSplitName, isSplitRequired, versionCode,
                versionCodeMajor, revisionCode, installLocation, verifiers, signingDetails,
                coreApp, debuggable, multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs,
                isolatedSplits, targetPackage, overlayIsStatic, overlayPriority, minSdkVersion,
                targetSdkVersion);
        return input.success(new PackageParser.ApkLite(codePath, packageSplit.first,
                packageSplit.second, isFeatureSplit, configForSplit, usesSplitName, isSplitRequired,
                versionCode, versionCodeMajor, revisionCode, installLocation, verifiers,
                signingDetails, coreApp, debuggable, multiArch, use32bitAbi, useEmbeddedDex,
                extractNativeLibs, isolatedSplits, targetPackage, overlayIsStatic, overlayPriority,
                minSdkVersion, targetSdkVersion));
    }

    public static ParseResult<Pair<String, String>> parsePackageSplitNames(ParseInput input,
            XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException {
        int type;
        while ((type = parser.next()) != XmlPullParser.START_TAG
                && type != XmlPullParser.END_DOCUMENT) {
        }

        if (type != XmlPullParser.START_TAG) {
            return input.error(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                    "No start tag found");
        }
        if (!parser.getName().equals(PackageParser.TAG_MANIFEST)) {
            return input.error(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
                    "No <manifest> tag");
        }

        final String packageName = attrs.getAttributeValue(null, "package");
        if (!"android".equals(packageName)) {
            final String error = PackageParser.validateName(packageName, true, true);
            if (error != null) {
                return input.error(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
                        "Invalid manifest package: " + error);
            }
        }

        String splitName = attrs.getAttributeValue(null, "split");
        if (splitName != null) {
            if (splitName.length() == 0) {
                splitName = null;
            } else {
                final String error = PackageParser.validateName(splitName, false, false);
                if (error != null) {
                    return input.error(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
                            "Invalid manifest split: " + error);
                }
            }
        }

        return input.success(Pair.create(packageName.intern(),
                (splitName != null) ? splitName.intern() : splitName));
    }

    public static VerifierInfo parseVerifier(AttributeSet attrs) {
+105 −54

File changed.

Preview size limit exceeded, changes collapsed.

+26 −0
Original line number Diff line number Diff line
@@ -18,12 +18,16 @@ package android.content.pm.parsing.result;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.parsing.ParsingUtils;
import android.os.ServiceManager;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;

import com.android.internal.compat.IPlatformCompat;
import com.android.internal.util.CollectionUtils;

/** @hide */
@@ -60,6 +64,28 @@ public class ParseTypeImpl implements ParseInput, ParseResult<Object> {
    private String mPackageName;
    private Integer mTargetSdkVersion;

    /**
     * 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
     * done outside of {@link com.android.server.pm.PackageManagerService}.
     */
    public static ParseTypeImpl forDefaultParsing() {
        IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
        return new ParseTypeImpl((changeId, packageName, targetSdkVersion) -> {
            ApplicationInfo appInfo = new ApplicationInfo();
            appInfo.packageName = packageName;
            appInfo.targetSdkVersion = targetSdkVersion;
            try {
                return platformCompat.isChangeEnabled(changeId, appInfo);
            } catch (Exception e) {
                // This shouldn't happen, but assume enforcement if it does
                Slog.wtf(ParsingUtils.TAG, "IPlatformCompat query failed", e);
                return true;
            }
        });
    }

    /**
     * @param callback if nullable, fallback to manual targetSdk > Q check
     */
Loading