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

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

Merge "Enable "quick install""

parents 924a4a1a 27c24fb8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1041,6 +1041,12 @@ public class PackageInstaller {
            installFlags |= PackageManager.INSTALL_FORCE_PERMISSION_PROMPT;
        }

        /** {@hide} */
        @SystemApi
        public void setInstallFlagsQuick() {
            installFlags |= PackageManager.INSTALL_QUICK;
        }

        /** {@hide} */
        public void dump(IndentingPrintWriter pw) {
            pw.printPair("mode", mode);
+8 −2
Original line number Diff line number Diff line
@@ -43,12 +43,10 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
import android.text.TextUtils;
import android.util.AndroidException;

import com.android.internal.util.ArrayUtils;
@@ -430,6 +428,14 @@ public abstract class PackageManager {
     */
    public static final int INSTALL_FORCE_PERMISSION_PROMPT = 0x00000400;

    /**
     * Flag parameter for {@link #installPackage} to indicate that this package is
     * to be installed quickly.
     *
     * @hide
     */
    public static final int INSTALL_QUICK = 0x00000800;

    /**
     * Flag parameter for
     * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
+28 −13
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MA
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;

import android.app.ActivityManager;
import android.content.ComponentName;
@@ -39,6 +40,7 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
import android.os.PatternMatcher;
import android.os.Trace;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -622,6 +624,8 @@ public class PackageParser {
    public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
    public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
    public final static int PARSE_ENFORCE_CODE = 1<<10;
    // TODO: fix b/25118622; remove this entirely once signature processing is quick
    public final static int PARSE_SKIP_VERIFICATION = 1<<11;

    private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();

@@ -920,7 +924,6 @@ public class PackageParser {
    private void parseSplitApk(Package pkg, int splitIndex, AssetManager assets, int flags)
            throws PackageParserException {
        final String apkPath = pkg.splitCodePaths[splitIndex];
        final File apkFile = new File(apkPath);

        mParseError = PackageManager.INSTALL_SUCCEEDED;
        mArchiveSourcePath = apkPath;
@@ -1054,33 +1057,38 @@ public class PackageParser {

    /**
     * Collect certificates from all the APKs described in the given package,
     * populating {@link Package#mSignatures}. This also asserts that all APK
     * populating {@link Package#mSignatures}.
     * <p>Depending upon the parser flags, this may also asserts that all APK
     * contents are signed correctly and consistently.
     */
    public void collectCertificates(Package pkg, int flags) throws PackageParserException {
    public void collectCertificates(Package pkg, int parseFlags) throws PackageParserException {
        pkg.mCertificates = null;
        pkg.mSignatures = null;
        pkg.mSigningKeys = null;

        collectCertificates(pkg, new File(pkg.baseCodePath), flags);
        collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags);

        if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
            for (String splitCodePath : pkg.splitCodePaths) {
                collectCertificates(pkg, new File(splitCodePath), flags);
                collectCertificates(pkg, new File(splitCodePath), parseFlags);
            }
        }
    }

    private static void collectCertificates(Package pkg, File apkFile, int flags)
    private static void collectCertificates(Package pkg, File apkFile, int parseFlags)
            throws PackageParserException {
        final boolean requireCode = ((flags & PARSE_ENFORCE_CODE) != 0)
        final boolean requireCode = ((parseFlags & PARSE_ENFORCE_CODE) != 0)
                && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0);
        final String apkPath = apkFile.getAbsolutePath();
        final boolean skipVerification = Build.IS_DEBUGGABLE
                && ((parseFlags & PARSE_SKIP_VERIFICATION) != 0);

        boolean codeFound = false;
        boolean codeFound = skipVerification;
        StrictJarFile jarFile = null;
        try {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
            jarFile = new StrictJarFile(apkPath);
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

            // Always verify manifest, regardless of source
            final ZipEntry manifestEntry = jarFile.findEntry(ANDROID_MANIFEST_FILENAME);
@@ -1089,11 +1097,12 @@ public class PackageParser {
                        "Package " + apkPath + " has no manifest");
            }

            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "buildVerifyList");
            final List<ZipEntry> toVerify = new ArrayList<>();
            toVerify.add(manifestEntry);

            // If we're parsing an untrusted package, verify all contents
            if ((flags & PARSE_IS_SYSTEM) == 0) {
            if (!skipVerification && (parseFlags & PARSE_IS_SYSTEM) == 0) {
                final Iterator<ZipEntry> i = jarFile.iterator();
                while (i.hasNext()) {
                    final ZipEntry entry = i.next();
@@ -1110,6 +1119,7 @@ public class PackageParser {
                    toVerify.add(entry);
                }
            }
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

            if (!codeFound && requireCode) {
                throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
@@ -1119,6 +1129,7 @@ public class PackageParser {
            // Verify that entries are signed consistently with the first entry
            // we encountered. Note that for splits, certificates may have
            // already been populated during an earlier parse of a base APK.
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyEntries");
            for (ZipEntry entry : toVerify) {
                final Certificate[][] entryCerts = loadCertificates(jarFile, entry);
                if (ArrayUtils.isEmpty(entryCerts)) {
@@ -1135,6 +1146,9 @@ public class PackageParser {
                    for (int i=0; i < entryCerts.length; i++) {
                        pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
                    }
                    if (skipVerification) {
                        break;
                    }
                } else {
                    if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
                        throw new PackageParserException(
@@ -1144,6 +1158,7 @@ public class PackageParser {
                    }
                }
            }
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        } catch (GeneralSecurityException e) {
            throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
                    "Failed to collect certificates from " + apkPath, e);
@@ -1199,7 +1214,8 @@ public class PackageParser {
            if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
                // TODO: factor signature related items out of Package object
                final Package tempPkg = new Package(null);
                collectCertificates(tempPkg, apkFile, 0);
                // TODO: fix b/25118622; pass in '0' for parse flags
                collectCertificates(tempPkg, apkFile, flags & PARSE_SKIP_VERIFICATION);
                signatures = tempPkg.mSignatures;
            } else {
                signatures = null;
@@ -1906,8 +1922,7 @@ public class PackageParser {
        return pkg;
    }

    private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs)
            throws XmlPullParserException, IOException {
    private FeatureInfo parseUsesFeature(Resources res, AttributeSet attrs) {
        FeatureInfo fi = new FeatureInfo();
        TypedArray sa = res.obtainAttributes(attrs,
                com.android.internal.R.styleable.AndroidManifestUsesFeature);
@@ -3960,7 +3975,7 @@ public class PackageParser {

    private boolean parseAllMetaData(Resources res,
            XmlPullParser parser, AttributeSet attrs, String tag,
            Component outInfo, String[] outError)
            Component<?> outInfo, String[] outError)
            throws XmlPullParserException, IOException {
        int outerDepth = parser.getDepth();
        int type;
+2 −9
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import android.util.Log;
import android.util.Slog;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -166,12 +165,7 @@ final class PackageDexOptimizer {
                    String oatDir = null;
                    if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
                        dexoptType = "dex2oat";
                        try {
                        oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
                        } catch (IOException ioe) {
                            Slog.w(TAG, "Unable to create oatDir for package: " + pkg.packageName);
                            return DEX_OPT_FAILED;
                        }
                    } else if (dexoptNeeded == DexFile.PATCHOAT_NEEDED) {
                        dexoptType = "patchoat";
                    } else if (dexoptNeeded == DexFile.SELF_PATCHOAT_NEEDED) {
@@ -230,8 +224,7 @@ final class PackageDexOptimizer {
     * cannot be created.
     */
    @Nullable
    private String createOatDirIfSupported(PackageParser.Package pkg, String dexInstructionSet)
            throws IOException {
    private String createOatDirIfSupported(PackageParser.Package pkg, String dexInstructionSet) {
        if (!pkg.canHaveOatDir()) {
            return null;
        }
+12 −3
Original line number Diff line number Diff line
@@ -481,6 +481,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
                    "Failed to resolve stage location", e);
        }
        final boolean quickInstall = (params.installFlags & PackageManager.INSTALL_QUICK) != 0;

        // Verify that stage looks sane with respect to existing application.
        // This currently only ensures packageName, versionCode, and certificate
@@ -488,7 +489,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        validateInstallLocked();

        Preconditions.checkNotNull(mPackageName);
        // TODO: fix b/25118622; don't bypass signature check
        if (!quickInstall) {
            Preconditions.checkNotNull(mSignatures);
        }
        Preconditions.checkNotNull(mResolvedBaseFile);

        if (!mPermissionsAccepted) {
@@ -598,6 +602,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
     * {@link PackageManagerService}.
     */
    private void validateInstallLocked() throws PackageManagerException {
        final boolean quickInstall = (params.installFlags & PackageManager.INSTALL_QUICK) != 0;
        mPackageName = null;
        mVersionCode = -1;
        mSignatures = null;
@@ -621,7 +626,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

            final ApkLite apk;
            try {
                apk = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
                // TODO: fix b/25118622; always use PARSE_COLLECT_CERTIFICATES
                final int parseFlags = quickInstall ? 0 : PackageParser.PARSE_COLLECT_CERTIFICATES;
                apk = PackageParser.parseApkLite(file, parseFlags);
            } catch (PackageParserException e) {
                throw PackageManagerException.from(e);
            }
@@ -742,6 +749,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    }

    private void assertApkConsistent(String tag, ApkLite apk) throws PackageManagerException {
        final boolean quickInstall = (params.installFlags & PackageManager.INSTALL_QUICK) != 0;
        if (!mPackageName.equals(apk.packageName)) {
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package "
                    + apk.packageName + " inconsistent with " + mPackageName);
@@ -751,7 +759,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                    + " version code " + apk.versionCode + " inconsistent with "
                    + mVersionCode);
        }
        if (!Signature.areExactMatch(mSignatures, apk.signatures)) {
        // TODO: fix b/25118622; don't bypass signature check
        if (!quickInstall && !Signature.areExactMatch(mSignatures, apk.signatures)) {
            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                    tag + " signatures are inconsistent");
        }
Loading