Improve robustness of package manager certificate collection.
The package manager contains an optimization which reuses cached
signatures instead of reloading them on startup if the package
appears to be unchanged. This commit adds an extra check to ensure
that the PackageSettings object actually has valid signatures since
it has happened that they have gone missing. Unfortunately it does
not address the root cause of the problem but it should alleviate the
symptoms after a reboot.
Bug: b/2547993
Change-Id: I41900c6a752711eb3a901360e3bb29aec946d0be
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index e6663d4..3908389 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -2496,16 +2496,25 @@
private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
PackageParser.Package pkg, File srcFile, int parseFlags) {
if (GET_CERTIFICATES) {
- if (ps == null || !ps.codePath.equals(srcFile)
- || ps.getTimeStamp() != srcFile.lastModified()) {
- Log.i(TAG, srcFile.toString() + " changed; collecting certs");
- if (!pp.collectCertificates(pkg, parseFlags)) {
- mLastScanError = pp.getParseError();
- return false;
+ if (ps != null
+ && ps.codePath.equals(srcFile)
+ && ps.getTimeStamp() == srcFile.lastModified()) {
+ if (ps.signatures.mSignatures != null
+ && ps.signatures.mSignatures.length != 0) {
+ // Optimization: reuse the existing cached certificates
+ // if the package appears to be unchanged.
+ pkg.mSignatures = ps.signatures.mSignatures;
+ return true;
}
+
+ Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them.");
} else {
- // Lets implicitly assign existing certificates.
- pkg.mSignatures = ps.signatures.mSignatures;
+ Log.i(TAG, srcFile.toString() + " changed; collecting certs");
+ }
+
+ if (!pp.collectCertificates(pkg, parseFlags)) {
+ mLastScanError = pp.getParseError();
+ return false;
}
}
return true;