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

Commit 9d8da4cd authored by Todd Kennedy's avatar Todd Kennedy Committed by Android (Google) Code Review
Browse files

Merge "Only parse an APK once" into nyc-dev

parents 1b83651e d9d438ac
Loading
Loading
Loading
Loading
+49 −7
Original line number Diff line number Diff line
@@ -385,6 +385,7 @@ public class PackageParser {
        public final int installLocation;
        public final VerifierInfo[] verifiers;
        public final Signature[] signatures;
        public final Certificate[][] certificates;
        public final boolean coreApp;
        public final boolean multiArch;
        public final boolean use32bitAbi;
@@ -392,8 +393,8 @@ public class PackageParser {

        public ApkLite(String codePath, String packageName, String splitName, int versionCode,
                int revisionCode, int installLocation, List<VerifierInfo> verifiers,
                Signature[] signatures, boolean coreApp, boolean multiArch, boolean use32bitAbi,
                boolean extractNativeLibs) {
                Signature[] signatures, Certificate[][] certificates, boolean coreApp,
                boolean multiArch, boolean use32bitAbi, boolean extractNativeLibs) {
            this.codePath = codePath;
            this.packageName = packageName;
            this.splitName = splitName;
@@ -402,6 +403,7 @@ public class PackageParser {
            this.installLocation = installLocation;
            this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
            this.signatures = signatures;
            this.certificates = certificates;
            this.coreApp = coreApp;
            this.multiArch = multiArch;
            this.use32bitAbi = use32bitAbi;
@@ -1073,6 +1075,43 @@ public class PackageParser {
        return APK_SIGNING_UNKNOWN;
    }

    /**
     * Populates the correct packages fields with the given certificates.
     * <p>
     * This is useful when we've already processed the certificates [such as during package
     * installation through an installer session]. We don't re-process the archive and
     * simply populate the correct fields.
     */
    public static void populateCertificates(Package pkg, Certificate[][] certificates)
            throws PackageParserException {
        pkg.mCertificates = null;
        pkg.mSignatures = null;
        pkg.mSigningKeys = null;

        pkg.mCertificates = certificates;
        try {
            pkg.mSignatures = convertToSignatures(certificates);
        } catch (CertificateEncodingException e) {
            // certificates weren't encoded properly; something went wrong
            throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
                    "Failed to collect certificates from " + pkg.baseCodePath, e);
        }
        pkg.mSigningKeys = new ArraySet<>(certificates.length);
        for (int i = 0; i < certificates.length; i++) {
            Certificate[] signerCerts = certificates[i];
            Certificate signerCert = signerCerts[0];
            pkg.mSigningKeys.add(signerCert.getPublicKey());
        }
        // add signatures to child packages
        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
        for (int i = 0; i < childCount; i++) {
            Package childPkg = pkg.childPackages.get(i);
            childPkg.mCertificates = pkg.mCertificates;
            childPkg.mSignatures = pkg.mSignatures;
            childPkg.mSigningKeys = pkg.mSigningKeys;
        }
    }

    /**
     * Collect certificates from all the APKs described in the given package,
     * populating {@link Package#mSignatures}. Also asserts that all APK
@@ -1304,6 +1343,7 @@ public class PackageParser {
            parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);

            final Signature[] signatures;
            final Certificate[][] certificates;
            if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
                // TODO: factor signature related items out of Package object
                final Package tempPkg = new Package(null);
@@ -1314,12 +1354,14 @@ public class PackageParser {
                    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                }
                signatures = tempPkg.mSignatures;
                certificates = tempPkg.mCertificates;
            } else {
                signatures = null;
                certificates = null;
            }

            final AttributeSet attrs = parser;
            return parseApkLite(apkPath, res, parser, attrs, flags, signatures);
            return parseApkLite(apkPath, res, parser, attrs, flags, signatures, certificates);

        } catch (XmlPullParserException | IOException | RuntimeException e) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
@@ -1405,8 +1447,8 @@ public class PackageParser {
    }

    private static ApkLite parseApkLite(String codePath, Resources res, XmlPullParser parser,
            AttributeSet attrs, int flags, Signature[] signatures) throws IOException,
            XmlPullParserException, PackageParserException {
            AttributeSet attrs, int flags, Signature[] signatures, Certificate[][] certificates)
                    throws IOException, XmlPullParserException, PackageParserException {
        final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);

        int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
@@ -1466,8 +1508,8 @@ public class PackageParser {
        }

        return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
                revisionCode, installLocation, verifiers, signatures, coreApp, multiArch,
                use32bitAbi, extractNativeLibs);
                revisionCode, installLocation, verifiers, signatures, certificates, coreApp,
                multiArch, use32bitAbi, extractNativeLibs);
    }

    /**
+4 −1
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.FileFilter;
import java.io.IOException;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -151,6 +152,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    private String mPackageName;
    private int mVersionCode;
    private Signature[] mSignatures;
    private Certificate[][] mCertificates;

    /**
     * Path to the validated base APK for this session, which may point at an
@@ -633,7 +635,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

        mRelinquished = true;
        mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
                installerPackageName, installerUid, user);
                installerPackageName, installerUid, user, mCertificates);
    }

    /**
@@ -695,6 +697,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            }
            if (mSignatures == null) {
                mSignatures = apk.signatures;
                mCertificates = apk.certificates;
            }

            assertApkConsistent(String.valueOf(addedFile), apk);
+34 −16
Original line number Diff line number Diff line
@@ -278,6 +278,7 @@ import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.text.SimpleDateFormat;
@@ -10977,7 +10978,8 @@ public class PackageManagerService extends IPackageManager.Stub {
                null /*originatingUri*/, null /*referrer*/, -1 /*originatingUid*/, callingUid);
        final InstallParams params = new InstallParams(origin, null /*moveInfo*/, observer,
                installFlags, installerPackageName, null /*volumeUuid*/, verificationInfo, user,
                null /*packageAbiOverride*/, null /*grantedPermissions*/);
                null /*packageAbiOverride*/, null /*grantedPermissions*/,
                null /*certificates*/);
        params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
        msg.obj = params;
@@ -10991,7 +10993,8 @@ public class PackageManagerService extends IPackageManager.Stub {
    void installStage(String packageName, File stagedDir, String stagedCid,
            IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
            String installerPackageName, int installerUid, UserHandle user) {
            String installerPackageName, int installerUid, UserHandle user,
            Certificate[][] certificates) {
        if (DEBUG_EPHEMERAL) {
            if ((sessionParams.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
                Slog.d(TAG, "Ephemeral install of " + packageName);
@@ -11012,7 +11015,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        final InstallParams params = new InstallParams(origin, null, observer,
                sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
                verificationInfo, user, sessionParams.abiOverride,
                sessionParams.grantedRuntimePermissions);
                sessionParams.grantedRuntimePermissions, certificates);
        params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
        msg.obj = params;
@@ -12107,11 +12110,12 @@ public class PackageManagerService extends IPackageManager.Stub {
        final String packageAbiOverride;
        final String[] grantedRuntimePermissions;
        final VerificationInfo verificationInfo;
        final Certificate[][] certificates;
        InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
                int installFlags, String installerPackageName, String volumeUuid,
                VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
                String[] grantedPermissions) {
                String[] grantedPermissions, Certificate[][] certificates) {
            super(user);
            this.origin = origin;
            this.move = move;
@@ -12122,6 +12126,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            this.verificationInfo = verificationInfo;
            this.packageAbiOverride = packageAbiOverride;
            this.grantedRuntimePermissions = grantedPermissions;
            this.certificates = certificates;
        }
        @Override
@@ -12590,6 +12595,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        /** If non-null, drop an async trace when the install completes */
        final String traceMethod;
        final int traceCookie;
        final Certificate[][] certificates;
        // The list of instruction sets supported by this app. This is currently
        // only used during the rmdex() phase to clean up resources. We can get rid of this
@@ -12600,7 +12606,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                int installFlags, String installerPackageName, String volumeUuid,
                UserHandle user, String[] instructionSets,
                String abiOverride, String[] installGrantPermissions,
                String traceMethod, int traceCookie) {
                String traceMethod, int traceCookie, Certificate[][] certificates) {
            this.origin = origin;
            this.move = move;
            this.installFlags = installFlags;
@@ -12613,6 +12619,7 @@ public class PackageManagerService extends IPackageManager.Stub {
            this.installGrantPermissions = installGrantPermissions;
            this.traceMethod = traceMethod;
            this.traceCookie = traceCookie;
            this.certificates = certificates;
        }
        abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
@@ -12705,9 +12712,9 @@ public class PackageManagerService extends IPackageManager.Stub {
        FileInstallArgs(InstallParams params) {
            super(params.origin, params.move, params.observer, params.installFlags,
                    params.installerPackageName, params.volumeUuid,
                    params.getUser(), null /* instruction sets */, params.packageAbiOverride,
                    params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
                    params.grantedRuntimePermissions,
                    params.traceMethod, params.traceCookie);
                    params.traceMethod, params.traceCookie, params.certificates);
            if (isFwdLocked()) {
                throw new IllegalArgumentException("Forward locking only supported in ASEC");
            }
@@ -12716,7 +12723,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        /** Existing install */
        FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
            super(OriginInfo.fromNothing(), null, null, 0, null, null, null, instructionSets,
                    null, null, null, 0);
                    null, null, null, 0, null /*certificates*/);
            this.codeFile = (codePath != null) ? new File(codePath) : null;
            this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
        }
@@ -12941,7 +12948,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                    params.installerPackageName, params.volumeUuid,
                    params.getUser(), null /* instruction sets */, params.packageAbiOverride,
                    params.grantedRuntimePermissions,
                    params.traceMethod, params.traceCookie);
                    params.traceMethod, params.traceCookie, params.certificates);
        }
        /** Existing install */
@@ -12949,7 +12956,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                        boolean isExternal, boolean isForwardLocked) {
            super(OriginInfo.fromNothing(), null, null, (isExternal ? INSTALL_EXTERNAL : 0)
              | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
                    instructionSets, null, null, null, 0);
                    instructionSets, null, null, null, 0, null /*certificates*/);
            // Hackily pretend we're still looking at a full code path
            if (!fullCodePath.endsWith(RES_FILE_NAME)) {
                fullCodePath = new File(fullCodePath, RES_FILE_NAME).getAbsolutePath();
@@ -12966,7 +12973,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
            super(OriginInfo.fromNothing(), null, null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
              | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
                    instructionSets, null, null, null, 0);
                    instructionSets, null, null, null, 0, null /*certificates*/);
            this.cid = cid;
            setMountPath(PackageHelper.getSdDir(cid));
        }
@@ -13235,7 +13242,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                    params.installerPackageName, params.volumeUuid,
                    params.getUser(), null /* instruction sets */, params.packageAbiOverride,
                    params.grantedRuntimePermissions,
                    params.traceMethod, params.traceCookie);
                    params.traceMethod, params.traceCookie, params.certificates);
        }
        int copyApk(IMediaContainerService imcs, boolean temp) {
@@ -14274,7 +14281,18 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
        try {
            // either use what we've been given or parse directly from the APK
            if (args.certificates != null) {
                try {
                    PackageParser.populateCertificates(pkg, args.certificates);
                } catch (PackageParserException e) {
                    // there was something wrong with the certificates we were given;
                    // try to pull them from the APK
                    PackageParser.collectCertificates(pkg, parseFlags);
                }
            } else {
                PackageParser.collectCertificates(pkg, parseFlags);
            }
        } catch (PackageParserException e) {
            res.setError("Failed collect during installPackageLI", e);
            return;
@@ -19159,7 +19177,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
        final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
        final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
                installerPackageName, volumeUuid, null /*verificationInfo*/, user,
                packageAbiOverride, null);
                packageAbiOverride, null /*grantedPermissions*/, null /*certificates*/);
        params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
        msg.obj = params;