Move signing data into SigningDetails container

This change replaces fields from Package that relate to signing
with a single SigningDetails container. It does the same with
InstallArgs and InstallParams. This simplifies much of the code
that would have otherwise relied on synchronizing many fields and
will enable PackageManagerService to make install-time descisions
based on package data instead of forcing it to be part of package
parsing.

This is a retake of ag/3382280

Test: android.appsecurity.cts.PkgInstallSignatureVerificationTest passes.
Test: atest google/perf/boottime/boottime-test to ensure no startup regression.
Bug: 68860689
Change-Id: I0df45ce537df5552a7e60e4d727a4dcef23c2252
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index c964f91..af20cd7 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -49,7 +49,6 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
-import com.android.server.pm.permission.BasePermission;
 
 import libcore.io.IoUtils;
 import org.xmlpull.v1.XmlPullParser;
@@ -302,7 +301,7 @@
             // into account but also allow the value from the old computation to avoid
             // data loss.
             final String[] signaturesSha256Digests = PackageUtils.computeSignaturesSha256Digests(
-                    pkg.mSignatures);
+                    pkg.mSigningDetails.signatures);
             final String signaturesSha256Digest = PackageUtils.computeSignaturesSha256Digest(
                     signaturesSha256Digests);
 
@@ -313,7 +312,7 @@
             }
 
             // For backwards compatibility we accept match based on first signature
-            if (pkg.mSignatures.length > 1 && currentCookieFile.equals(computeInstantCookieFile(
+            if (pkg.mSigningDetails.signatures.length > 1 && currentCookieFile.equals(computeInstantCookieFile(
                     pkg.packageName, signaturesSha256Digests[0], userId))) {
                 return;
             }
@@ -1176,12 +1175,13 @@
             // We prefer the modern computation procedure where all certs are taken
             // into account and delete the file derived via the legacy hash computation.
             File newCookieFile = computeInstantCookieFile(pkg.packageName,
-                    PackageUtils.computeSignaturesSha256Digest(pkg.mSignatures), userId);
-            if (pkg.mSignatures.length > 0) {
-                File oldCookieFile = peekInstantCookieFile(pkg.packageName, userId);
-                if (oldCookieFile != null && !newCookieFile.equals(oldCookieFile)) {
-                    oldCookieFile.delete();
-                }
+                    PackageUtils.computeSignaturesSha256Digest(pkg.mSigningDetails.signatures), userId);
+            if (!pkg.mSigningDetails.hasSignatures()) {
+                Slog.wtf(LOG_TAG, "Parsed Instant App contains no valid signatures!");
+            }
+            File oldCookieFile = peekInstantCookieFile(pkg.packageName, userId);
+            if (oldCookieFile != null && !newCookieFile.equals(oldCookieFile)) {
+                oldCookieFile.delete();
             }
             cancelPendingPersistLPw(pkg, userId);
             addPendingPersistCookieLPw(userId, pkg, cookie, newCookieFile);
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index fca9585..93d3b77 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -188,7 +188,7 @@
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                     "Passed invalid package to keyset validation.");
         }
-        ArraySet<PublicKey> signingKeys = pkg.mSigningKeys;
+        ArraySet<PublicKey> signingKeys = pkg.mSigningDetails.publicKeys;
         if (signingKeys == null || !(signingKeys.size() > 0) || signingKeys.contains(null)) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                     "Package has invalid signing-key-set.");
@@ -223,7 +223,7 @@
         PackageSetting ps = mPackages.get(pkg.packageName);
         Preconditions.checkNotNull(ps, "pkg: " + pkg.packageName
                     + "does not have a corresponding entry in mPackages.");
-        addSigningKeySetToPackageLPw(ps, pkg.mSigningKeys);
+        addSigningKeySetToPackageLPw(ps, pkg.mSigningDetails.publicKeys);
         if (pkg.mKeySetMapping != null) {
             addDefinedKeySetsToPackageLPw(ps, pkg.mKeySetMapping);
             if (pkg.mUpgradeKeySets != null) {
@@ -371,7 +371,7 @@
         long[] upgradeKeySets = oldPS.keySetData.getUpgradeKeySets();
         for (int i = 0; i < upgradeKeySets.length; i++) {
             Set<PublicKey> upgradeSet = getPublicKeysFromKeySetLPr(upgradeKeySets[i]);
-            if (upgradeSet != null && newPkg.mSigningKeys.containsAll(upgradeSet)) {
+            if (upgradeSet != null && newPkg.mSigningDetails.publicKeys.containsAll(upgradeSet)) {
                 return true;
             }
         }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5577de8..4e91898 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -58,7 +58,6 @@
 import android.content.pm.PackageParser.ApkLite;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.Signature;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.os.Binder;
@@ -84,6 +83,7 @@
 import android.util.ExceptionUtils;
 import android.util.MathUtils;
 import android.util.Slog;
+import android.util.apk.ApkSignatureVerifier;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.NativeLibraryHelper;
@@ -107,7 +107,7 @@
 import java.io.FileFilter;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -227,9 +227,7 @@
     @GuardedBy("mLock")
     private long mVersionCode;
     @GuardedBy("mLock")
-    private Signature[] mSignatures;
-    @GuardedBy("mLock")
-    private Certificate[][] mCertificates;
+    private PackageParser.SigningDetails mSigningDetails;
 
     /**
      * Path to the validated base APK for this session, which may point at an
@@ -857,7 +855,7 @@
         }
 
         Preconditions.checkNotNull(mPackageName);
-        Preconditions.checkNotNull(mSignatures);
+        Preconditions.checkNotNull(mSigningDetails);
         Preconditions.checkNotNull(mResolvedBaseFile);
 
         if (needToAskForPermissionsLocked()) {
@@ -938,7 +936,7 @@
 
         mRelinquished = true;
         mPm.installStage(mPackageName, stageDir, localObserver, params,
-                mInstallerPackageName, mInstallerUid, user, mCertificates);
+                mInstallerPackageName, mInstallerUid, user, mSigningDetails);
     }
 
     /**
@@ -957,7 +955,7 @@
             throws PackageManagerException {
         mPackageName = null;
         mVersionCode = -1;
-        mSignatures = null;
+        mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
 
         mResolvedBaseFile = null;
         mResolvedStagedFiles.clear();
@@ -1009,9 +1007,8 @@
                 mPackageName = apk.packageName;
                 mVersionCode = apk.getLongVersionCode();
             }
-            if (mSignatures == null) {
-                mSignatures = apk.signatures;
-                mCertificates = apk.certificates;
+            if (mSigningDetails == PackageParser.SigningDetails.UNKNOWN) {
+                mSigningDetails = apk.signingDetails;
             }
 
             assertApkConsistentLocked(String.valueOf(addedFile), apk);
@@ -1060,8 +1057,15 @@
                 mPackageName = pkgInfo.packageName;
                 mVersionCode = pkgInfo.getLongVersionCode();
             }
-            if (mSignatures == null) {
-                mSignatures = pkgInfo.signatures;
+            if (mSigningDetails == PackageParser.SigningDetails.UNKNOWN) {
+                try {
+                    mSigningDetails = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts(
+                            pkgInfo.applicationInfo.sourceDir,
+                            PackageParser.SigningDetails.SignatureSchemeVersion.JAR);
+                } catch (PackageParserException e) {
+                    throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                            "Couldn't obtain signatures from base APK");
+                }
             }
         }
 
@@ -1155,7 +1159,7 @@
                     + " version code " + apk.versionCode + " inconsistent with "
                     + mVersionCode);
         }
-        if (!Signature.areExactMatch(mSignatures, apk.signatures)) {
+        if (!mSigningDetails.signaturesMatchExactly(apk.signingDetails)) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                     tag + " signatures are inconsistent");
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 44aad44..c02ce09 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -176,6 +176,7 @@
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.PackageParser.ParseFlags;
 import android.content.pm.PackageParser.ServiceIntentInfo;
+import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
 import android.content.pm.PackageStats;
 import android.content.pm.PackageUserState;
 import android.content.pm.ParceledListSlice;
@@ -337,7 +338,6 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
 import java.security.SecureRandom;
-import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -5360,7 +5360,7 @@
                     || filterAppAccessLPr(ps2, callingUid, callingUserId)) {
                 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
             }
-            return compareSignatures(p1.mSignatures, p2.mSignatures);
+            return compareSignatures(p1.mSigningDetails.signatures, p2.mSigningDetails.signatures);
         }
     }
 
@@ -8194,20 +8194,19 @@
                 && ps.timeStamp == lastModifiedTime
                 && !isCompatSignatureUpdateNeeded(pkg)
                 && !isRecoverSignatureUpdateNeeded(pkg)) {
-            long mSigningKeySetId = ps.keySetData.getProperSigningKeySet();
-            final KeySetManagerService ksms = mSettings.mKeySetManagerService;
-            ArraySet<PublicKey> signingKs;
-            synchronized (mPackages) {
-                signingKs = ksms.getPublicKeysFromKeySetLPr(mSigningKeySetId);
-            }
             if (ps.signatures.mSignatures != null
                     && ps.signatures.mSignatures.length != 0
-                    && signingKs != null) {
-                // Optimization: reuse the existing cached certificates
+                    && ps.signatures.mSignatureSchemeVersion != SignatureSchemeVersion.UNKNOWN) {
+                // Optimization: reuse the existing cached signing data
                 // if the package appears to be unchanged.
-                pkg.mSignatures = ps.signatures.mSignatures;
-                pkg.mSigningKeys = signingKs;
-                return;
+                try {
+                    pkg.mSigningDetails = new PackageParser.SigningDetails(ps.signatures.mSignatures,
+                            ps.signatures.mSignatureSchemeVersion);
+                    return;
+                } catch (CertificateException e) {
+                    Slog.e(TAG, "Attempt to read public keys from persisted signatures failed for "
+                                    + ps.name, e);
+                }
             }
 
             Slog.w(TAG, "PackageSetting for " + ps.name
@@ -8546,7 +8545,7 @@
              * Check to make sure the signatures match first. If they don't,
              * wipe the installed application and its data.
              */
-            if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
+            if (compareSignatures(ps.signatures.mSignatures, pkg.mSigningDetails.signatures)
                     != PackageManager.SIGNATURE_MATCH) {
                 logCriticalInfo(Log.WARN, "Package " + ps.name + " appeared on system, but"
                         + " signatures don't match existing userdata copy; removing");
@@ -9518,9 +9517,10 @@
                     final String[] expectedCertDigests = requiredCertDigests[i];
                     // For apps targeting O MR1 we require explicit enumeration of all certs.
                     final String[] libCertDigests = (targetSdk > Build.VERSION_CODES.O)
-                            ? PackageUtils.computeSignaturesSha256Digests(libPkg.mSignatures)
+                            ? PackageUtils.computeSignaturesSha256Digests(
+                            libPkg.mSigningDetails.signatures)
                             : PackageUtils.computeSignaturesSha256Digests(
-                                    new Signature[]{libPkg.mSignatures[0]});
+                                    new Signature[]{libPkg.mSigningDetails.signatures[0]});
 
                     // Take a shortcut if sizes don't match. Note that if an app doesn't
                     // target O we don't parse the "additional-certificate" tags similarly
@@ -9856,14 +9856,14 @@
             if (ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) {
                 // We just determined the app is signed correctly, so bring
                 // over the latest parsed certs.
-                pkgSetting.signatures.mSignatures = pkg.mSignatures;
+                pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
             } else {
                 if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                     throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                             "Package " + pkg.packageName + " upgrade keys do not match the "
                                     + "previously installed version");
                 } else {
-                    pkgSetting.signatures.mSignatures = pkg.mSignatures;
+                    pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
                     String msg = "System package " + pkg.packageName
                             + " signature changed; retaining data.";
                     reportSettingsProblem(Log.WARN, msg);
@@ -9873,8 +9873,8 @@
             try {
                 final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg);
                 final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg);
-                final boolean compatMatch = verifySignatures(signatureCheckPs, pkg.mSignatures,
-                        compareCompat, compareRecover);
+                final boolean compatMatch = verifySignatures(signatureCheckPs,
+                        pkg.mSigningDetails, compareCompat, compareRecover);
                 // The new KeySets will be re-added later in the scanning process.
                 if (compatMatch) {
                     synchronized (mPackages) {
@@ -9883,14 +9883,14 @@
                 }
                 // We just determined the app is signed correctly, so bring
                 // over the latest parsed certs.
-                pkgSetting.signatures.mSignatures = pkg.mSignatures;
+                pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
             } catch (PackageManagerException e) {
                 if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                     throw e;
                 }
                 // The signature has changed, but this package is in the system
                 // image...  let's recover!
-                pkgSetting.signatures.mSignatures = pkg.mSignatures;
+                pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
                 // However...  if this package is part of a shared user, but it
                 // doesn't match the signature of the shared user, let's fail.
                 // What this means is that you can't change the signatures
@@ -9898,7 +9898,7 @@
                 // that unreasonable.
                 if (signatureCheckPs.sharedUser != null) {
                     if (compareSignatures(signatureCheckPs.sharedUser.signatures.mSignatures,
-                            pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
+                            pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH) {
                         throw new PackageManagerException(
                                 INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
                                 "Signature mismatch for shared user: "
@@ -13204,7 +13204,7 @@
     void installStage(String packageName, File stagedDir,
             IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
             String installerPackageName, int installerUid, UserHandle user,
-            Certificate[][] certificates) {
+            PackageParser.SigningDetails signingDetails) {
         if (DEBUG_EPHEMERAL) {
             if ((sessionParams.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
                 Slog.d(TAG, "Ephemeral install of " + packageName);
@@ -13222,7 +13222,7 @@
         final InstallParams params = new InstallParams(origin, null, observer,
                 sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
                 verificationInfo, user, sessionParams.abiOverride,
-                sessionParams.grantedRuntimePermissions, certificates, installReason);
+                sessionParams.grantedRuntimePermissions, signingDetails, installReason);
         params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
 
@@ -13826,7 +13826,7 @@
             final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName);
             if (pkg == null) {
                 return -1;
-            } else if (pkg.mSignatures.length != 1) {
+            } else if (pkg.mSigningDetails.signatures.length != 1) {
                 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
                         + " has more than one signature; ignoring");
                 return -1;
@@ -13840,7 +13840,7 @@
 
             final byte[] expectedPublicKey;
             try {
-                final Signature verifierSig = pkg.mSignatures[0];
+                final Signature verifierSig = pkg.mSigningDetails.signatures[0];
                 final PublicKey publicKey = verifierSig.getPublicKey();
                 expectedPublicKey = publicKey.getEncoded();
             } catch (CertificateException e) {
@@ -14532,13 +14532,13 @@
         final String packageAbiOverride;
         final String[] grantedRuntimePermissions;
         final VerificationInfo verificationInfo;
-        final Certificate[][] certificates;
+        final PackageParser.SigningDetails signingDetails;
         final int installReason;
 
         InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
                 int installFlags, String installerPackageName, String volumeUuid,
                 VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
-                String[] grantedPermissions, Certificate[][] certificates, int installReason) {
+                String[] grantedPermissions, PackageParser.SigningDetails signingDetails, int installReason) {
             super(user);
             this.origin = origin;
             this.move = move;
@@ -14549,7 +14549,7 @@
             this.verificationInfo = verificationInfo;
             this.packageAbiOverride = packageAbiOverride;
             this.grantedRuntimePermissions = grantedPermissions;
-            this.certificates = certificates;
+            this.signingDetails = signingDetails;
             this.installReason = installReason;
         }
 
@@ -14980,7 +14980,7 @@
         /** If non-null, drop an async trace when the install completes */
         final String traceMethod;
         final int traceCookie;
-        final Certificate[][] certificates;
+        final PackageParser.SigningDetails signingDetails;
         final int installReason;
 
         // The list of instruction sets supported by this app. This is currently
@@ -14992,7 +14992,7 @@
                 int installFlags, String installerPackageName, String volumeUuid,
                 UserHandle user, String[] instructionSets,
                 String abiOverride, String[] installGrantPermissions,
-                String traceMethod, int traceCookie, Certificate[][] certificates,
+                String traceMethod, int traceCookie, PackageParser.SigningDetails signingDetails,
                 int installReason) {
             this.origin = origin;
             this.move = move;
@@ -15006,7 +15006,7 @@
             this.installGrantPermissions = installGrantPermissions;
             this.traceMethod = traceMethod;
             this.traceCookie = traceCookie;
-            this.certificates = certificates;
+            this.signingDetails = signingDetails;
             this.installReason = installReason;
         }
 
@@ -15102,7 +15102,7 @@
                     params.installerPackageName, params.volumeUuid,
                     params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
                     params.grantedRuntimePermissions,
-                    params.traceMethod, params.traceCookie, params.certificates,
+                    params.traceMethod, params.traceCookie, params.signingDetails,
                     params.installReason);
             if (isFwdLocked()) {
                 throw new IllegalArgumentException("Forward locking only supported in ASEC");
@@ -15112,7 +15112,7 @@
         /** Existing install */
         FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
             super(OriginInfo.fromNothing(), null, null, 0, null, null, null, instructionSets,
-                    null, null, null, 0, null /*certificates*/,
+                    null, null, null, 0, PackageParser.SigningDetails.UNKNOWN,
                     PackageManager.INSTALL_REASON_UNKNOWN);
             this.codeFile = (codePath != null) ? new File(codePath) : null;
             this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
@@ -15333,7 +15333,7 @@
                     params.installerPackageName, params.volumeUuid,
                     params.getUser(), null /* instruction sets */, params.packageAbiOverride,
                     params.grantedRuntimePermissions,
-                    params.traceMethod, params.traceCookie, params.certificates,
+                    params.traceMethod, params.traceCookie, params.signingDetails,
                     params.installReason);
         }
 
@@ -15672,7 +15672,8 @@
                 }
             } else {
                 // default to original signature matching
-                if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures)
+                if (compareSignatures(oldPackage.mSigningDetails.signatures,
+                        pkg.mSigningDetails.signatures)
                         != PackageManager.SIGNATURE_MATCH) {
                     res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
                             "New package has a different signature: " + pkgName);
@@ -16484,14 +16485,8 @@
 
         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);
-                }
+            if (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) {
+                pkg.setSigningDetails(args.signingDetails);
             } else {
                 PackageParser.collectCertificates(pkg, parseFlags);
             }
@@ -16610,7 +16605,8 @@
                         final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg);
                         final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg);
                         final boolean compatMatch = verifySignatures(
-                                signatureCheckPs, pkg.mSignatures, compareCompat, compareRecover);
+                                signatureCheckPs, pkg.mSigningDetails, compareCompat,
+                                compareRecover);
                         // The new KeySets will be re-added later in the scanning process.
                         if (compatMatch) {
                             synchronized (mPackages) {
@@ -16661,7 +16657,7 @@
                         sigsOk = ksms.checkUpgradeKeySetLocked(sourcePackageSetting, pkg);
                     } else {
                         sigsOk = compareSignatures(sourcePackageSetting.signatures.mSignatures,
-                                pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;
+                                pkg.mSigningDetails.signatures) == PackageManager.SIGNATURE_MATCH;
                     }
                     if (!sigsOk) {
                         // If the owning package is the system itself, we log but allow
@@ -16937,7 +16933,8 @@
                 for (ActivityIntentInfo filter : a.intents) {
                     if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
                         if (DEBUG_DOMAIN_VERIFICATION) {
-                            Slog.d(TAG, "Intent filter needs verification, so processing all filters");
+                            Slog.d(TAG,
+                                    "Intent filter needs verification, so processing all filters");
                         }
                         needToVerify = true;
                         break;
@@ -22245,8 +22242,8 @@
         final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
         final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
                 installerPackageName, volumeUuid, null /*verificationInfo*/, user,
-                packageAbiOverride, null /*grantedPermissions*/, null /*certificates*/,
-                PackageManager.INSTALL_REASON_UNKNOWN);
+                packageAbiOverride, null /*grantedPermissions*/,
+                PackageParser.SigningDetails.UNKNOWN, PackageManager.INSTALL_REASON_UNKNOWN);
         params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 20ec9b5..df836de 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -504,13 +504,13 @@
      * system upgrade) and {@code scannedSigs} will be in the newer format.
      */
     private static boolean matchSignaturesCompat(String packageName,
-            PackageSignatures packageSignatures, Signature[] parsedSignatures) {
+            PackageSignatures packageSignatures, PackageParser.SigningDetails parsedSignatures) {
         ArraySet<Signature> existingSet = new ArraySet<Signature>();
         for (Signature sig : packageSignatures.mSignatures) {
             existingSet.add(sig);
         }
         ArraySet<Signature> scannedCompatSet = new ArraySet<Signature>();
-        for (Signature sig : parsedSignatures) {
+        for (Signature sig : parsedSignatures.signatures) {
             try {
                 Signature[] chainSignatures = sig.getChainSignatures();
                 for (Signature chainSig : chainSignatures) {
@@ -552,21 +552,25 @@
      * @throws PackageManagerException if the signatures did not match.
      */
     public static boolean verifySignatures(PackageSetting pkgSetting,
-            Signature[] parsedSignatures, boolean compareCompat, boolean compareRecover)
+            PackageParser.SigningDetails parsedSignatures, boolean compareCompat,
+            boolean compareRecover)
             throws PackageManagerException {
         final String packageName = pkgSetting.name;
         boolean compatMatch = false;
         if (pkgSetting.signatures.mSignatures != null) {
             // Already existing package. Make sure signatures match
-            boolean match = compareSignatures(pkgSetting.signatures.mSignatures, parsedSignatures)
+            boolean match = compareSignatures(pkgSetting.signatures.mSignatures,
+                    parsedSignatures.signatures)
                     == PackageManager.SIGNATURE_MATCH;
             if (!match && compareCompat) {
-                match = matchSignaturesCompat(packageName, pkgSetting.signatures, parsedSignatures);
+                match = matchSignaturesCompat(packageName, pkgSetting.signatures,
+                        parsedSignatures);
                 compatMatch = match;
             }
             if (!match && compareRecover) {
                 match = matchSignaturesRecover(
-                        packageName, pkgSetting.signatures.mSignatures, parsedSignatures);
+                        packageName, pkgSetting.signatures.mSignatures,
+                        parsedSignatures.signatures);
             }
             if (!match) {
                 throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
@@ -578,14 +582,14 @@
         if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
             // Already existing package. Make sure signatures match
             boolean match = compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
-                    parsedSignatures) == PackageManager.SIGNATURE_MATCH;
+                    parsedSignatures.signatures) == PackageManager.SIGNATURE_MATCH;
             if (!match && compareCompat) {
                 match = matchSignaturesCompat(
                         packageName, pkgSetting.sharedUser.signatures, parsedSignatures);
             }
             if (!match && compareRecover) {
-                match = matchSignaturesRecover(
-                        packageName, pkgSetting.sharedUser.signatures.mSignatures, parsedSignatures);
+                match = matchSignaturesRecover(packageName,
+                        pkgSetting.sharedUser.signatures.mSignatures, parsedSignatures.signatures);
                 compatMatch |= match;
             }
             if (!match) {
diff --git a/services/core/java/com/android/server/pm/PackageSignatures.java b/services/core/java/com/android/server/pm/PackageSignatures.java
index f5c81e4..d567d5c 100644
--- a/services/core/java/com/android/server/pm/PackageSignatures.java
+++ b/services/core/java/com/android/server/pm/PackageSignatures.java
@@ -22,6 +22,8 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
 import android.content.pm.Signature;
 import android.util.Log;
 
@@ -30,15 +32,17 @@
 
 class PackageSignatures {
     Signature[] mSignatures;
+    @SignatureSchemeVersion int mSignatureSchemeVersion;
 
     PackageSignatures(PackageSignatures orig) {
         if (orig != null && orig.mSignatures != null) {
             mSignatures = orig.mSignatures.clone();
+            mSignatureSchemeVersion = orig.mSignatureSchemeVersion;
         }
     }
 
-    PackageSignatures(Signature[] sigs) {
-        assignSignatures(sigs);
+    PackageSignatures(PackageParser.SigningDetails signingDetails) {
+        assignSignatures(signingDetails);
     }
 
     PackageSignatures() {
@@ -52,6 +56,7 @@
         serializer.startTag(null, tagName);
         serializer.attribute(null, "count",
                 Integer.toString(mSignatures.length));
+        serializer.attribute(null, "schemeVersion", Integer.toString(mSignatureSchemeVersion));
         for (int i=0; i<mSignatures.length; i++) {
             serializer.startTag(null, "cert");
             final Signature sig = mSignatures[i];
@@ -84,6 +89,15 @@
                        + " no count at " + parser.getPositionDescription());
             XmlUtils.skipCurrentTag(parser);
         }
+        String schemeVersionStr = parser.getAttributeValue(null, "schemeVersion");
+        if (schemeVersionStr == null) {
+            PackageManagerService.reportSettingsProblem(Log.WARN,
+                    "Error in package manager settings: <signatures> has no schemeVersion at "
+                        + parser.getPositionDescription());
+            mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
+        } else {
+            mSignatureSchemeVersion = Integer.parseInt(countStr);
+        }
         final int count = Integer.parseInt(countStr);
         mSignatures = new Signature[count];
         int pos = 0;
@@ -174,14 +188,15 @@
         }
     }
 
-    void assignSignatures(Signature[] sigs) {
-        if (sigs == null) {
+    void assignSignatures(PackageParser.SigningDetails signingDetails) {
+        mSignatureSchemeVersion = signingDetails.signatureSchemeVersion;
+        if (!signingDetails.hasSignatures()) {
             mSignatures = null;
             return;
         }
-        mSignatures = new Signature[sigs.length];
-        for (int i=0; i<sigs.length; i++) {
-            mSignatures[i] = sigs[i];
+        mSignatures = new Signature[signingDetails.signatures.length];
+        for (int i=0; i<signingDetails.signatures.length; i++) {
+            mSignatures[i] = signingDetails.signatures[i];
         }
     }
 
@@ -190,7 +205,9 @@
         StringBuffer buf = new StringBuffer(128);
         buf.append("PackageSignatures{");
         buf.append(Integer.toHexString(System.identityHashCode(this)));
-        buf.append(" [");
+        buf.append(" version:");
+        buf.append(mSignatureSchemeVersion);
+        buf.append(", signatures:[");
         if (mSignatures != null) {
             for (int i=0; i<mSignatures.length; i++) {
                 if (i > 0) buf.append(", ");
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index fbf3d82..37f9a74 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -17,8 +17,6 @@
 package com.android.server.pm;
 
 import android.content.pm.PackageParser;
-import android.content.pm.PackageUserState;
-import android.content.pm.SELinuxUtil;
 import android.content.pm.Signature;
 import android.os.Environment;
 import android.util.Slog;
@@ -453,7 +451,7 @@
     public String getMatchedSeInfo(PackageParser.Package pkg) {
         // Check for exact signature matches across all certs.
         Signature[] certs = mCerts.toArray(new Signature[0]);
-        if (!Signature.areExactMatch(certs, pkg.mSignatures)) {
+        if (!Signature.areExactMatch(certs, pkg.mSigningDetails.signatures)) {
             return null;
         }
 
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 4cf1814..ed80c70 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -955,7 +955,7 @@
         }
         // Update signatures if needed.
         if (p.signatures.mSignatures == null) {
-            p.signatures.assignSignatures(pkg.mSignatures);
+            p.signatures.assignSignatures(pkg.mSigningDetails);
         }
         // Update flags if needed.
         if (pkg.applicationInfo.flags != p.pkgFlags) {
@@ -964,7 +964,7 @@
         // If this app defines a shared user id initialize
         // the shared user signatures as well.
         if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
-            p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
+            p.sharedUser.signatures.assignSignatures(pkg.mSigningDetails);
         }
         // Update static shared library dependencies if needed
         if (pkg.usesStaticLibraries != null && pkg.usesStaticLibrariesVersions != null
@@ -4565,10 +4565,8 @@
             }
             pw.print(prefix); pw.print("  versionName="); pw.println(ps.pkg.mVersionName);
             pw.print(prefix); pw.print("  splits="); dumpSplitNames(pw, ps.pkg); pw.println();
-            final int apkSigningVersion = PackageParser.getApkSigningVersion(ps.pkg);
-            if (apkSigningVersion != PackageParser.APK_SIGNING_UNKNOWN) {
-                pw.print(prefix); pw.print("  apkSigningVersion="); pw.println(apkSigningVersion);
-            }
+            final int apkSigningVersion = ps.pkg.mSigningDetails.signatureSchemeVersion;
+            pw.print(prefix); pw.print("  apkSigningVersion="); pw.println(apkSigningVersion);
             pw.print(prefix); pw.print("  applicationInfo=");
                 pw.println(ps.pkg.applicationInfo.toString());
             pw.print(prefix); pw.print("  flags="); printFlags(pw, ps.pkg.applicationInfo.flags,
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 34c3ce3..6e07eaa 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -27,7 +27,6 @@
 import android.companion.CompanionDeviceManager;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageList;
@@ -62,8 +61,6 @@
 import android.util.Xml;
 import com.android.internal.util.XmlUtils;
 import com.android.server.LocalServices;
-import com.android.server.pm.PackageManagerService;
-import com.android.server.pm.PackageSetting;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -1169,7 +1166,8 @@
         final String systemPackageName = mServiceInternal.getKnownPackageName(
                 PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM);
         final PackageParser.Package systemPackage = getPackage(systemPackageName);
-        return compareSignatures(systemPackage.mSignatures, pkg.mSignatures)
+        return compareSignatures(systemPackage.mSigningDetails.signatures,
+                pkg.mSigningDetails.signatures)
                 == PackageManager.SIGNATURE_MATCH;
     }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 90ac4ab..786b998 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -29,7 +29,6 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
@@ -56,21 +55,17 @@
 import android.util.Slog;
 import android.util.SparseArray;
 
-import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.RoSystemProperties;
 import com.android.internal.util.ArrayUtils;
-import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.SystemConfig;
 import com.android.server.Watchdog;
-import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.PackageManagerServiceUtils;
 import com.android.server.pm.PackageSetting;
-import com.android.server.pm.ProcessLoggingHandler;
 import com.android.server.pm.SharedUserSetting;
 import com.android.server.pm.UserManagerService;
 import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback;
@@ -1015,10 +1010,10 @@
         final PackageParser.Package systemPackage =
                 mPackageManagerInt.getPackage(systemPackageName);
         boolean allowed = (PackageManagerServiceUtils.compareSignatures(
-                                bp.getSourceSignatures(), pkg.mSignatures)
+                                bp.getSourceSignatures(), pkg.mSigningDetails.signatures)
                         == PackageManager.SIGNATURE_MATCH)
                 || (PackageManagerServiceUtils.compareSignatures(
-                                systemPackage.mSignatures, pkg.mSignatures)
+                systemPackage.mSigningDetails.signatures, pkg.mSigningDetails.signatures)
                         == PackageManager.SIGNATURE_MATCH);
         if (!allowed && (privilegedPermission || oemPermission)) {
             if (pkg.isSystem()) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 32b0b26..49601c3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -34,7 +34,6 @@
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.nio.charset.StandardCharsets;
-import java.security.cert.Certificate;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -262,14 +261,13 @@
         assertBundleApproximateEquals(a.mAppMetaData, b.mAppMetaData);
         assertEquals(a.mVersionName, b.mVersionName);
         assertEquals(a.mSharedUserId, b.mSharedUserId);
-        assertTrue(Arrays.equals(a.mSignatures, b.mSignatures));
-        assertTrue(Arrays.equals(a.mCertificates, b.mCertificates));
+        assertTrue(Arrays.equals(a.mSigningDetails.signatures, b.mSigningDetails.signatures));
         assertTrue(Arrays.equals(a.mLastPackageUsageTimeInMills, b.mLastPackageUsageTimeInMills));
         assertEquals(a.mExtras, b.mExtras);
         assertEquals(a.mRestrictedAccountType, b.mRestrictedAccountType);
         assertEquals(a.mRequiredAccountType, b.mRequiredAccountType);
         assertEquals(a.mOverlayTarget, b.mOverlayTarget);
-        assertEquals(a.mSigningKeys, b.mSigningKeys);
+        assertEquals(a.mSigningDetails.publicKeys, b.mSigningDetails.publicKeys);
         assertEquals(a.mUpgradeKeySets, b.mUpgradeKeySets);
         assertEquals(a.mKeySetMapping, b.mKeySetMapping);
         assertEquals(a.cpuAbiOverride, b.cpuAbiOverride);
@@ -495,14 +493,16 @@
         pkg.mAppMetaData = new Bundle();
         pkg.mVersionName = "foo17";
         pkg.mSharedUserId = "foo18";
-        pkg.mSignatures = new Signature[] { new Signature(new byte[16]) };
-        pkg.mCertificates = new Certificate[][] { new Certificate[] { null }};
+        pkg.mSigningDetails =
+                new PackageParser.SigningDetails(
+                        new Signature[] { new Signature(new byte[16]) },
+                        2,
+                        new ArraySet<>());
         pkg.mExtras = new Bundle();
         pkg.mRestrictedAccountType = "foo19";
         pkg.mRequiredAccountType = "foo20";
         pkg.mOverlayTarget = "foo21";
         pkg.mOverlayPriority = 100;
-        pkg.mSigningKeys = new ArraySet<>();
         pkg.mUpgradeKeySets = new ArraySet<>();
         pkg.mKeySetMapping = new ArrayMap<>();
         pkg.cpuAbiOverride = "foo22";