am d80cf910: Merge "Allow codepath changes for new OTA packages" into mnc-dev
* commit 'd80cf9109aa6b560e473f0197034085ed9062eaa':
Allow codepath changes for new OTA packages
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3c117aa..f4bde25 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -477,6 +477,13 @@
final ArrayMap<String, ArrayMap<String, PackageParser.Package>> mOverlays =
new ArrayMap<String, ArrayMap<String, PackageParser.Package>>();
+ /**
+ * Tracks new system packages [receiving in an OTA] that we expect to
+ * find updated user-installed versions. Keys are package name, values
+ * are package location.
+ */
+ final private ArrayMap<String, File> mExpectingBetter = new ArrayMap<>();
+
final Settings mSettings;
boolean mRestoredSettings;
@@ -2053,7 +2060,6 @@
// Prune any system packages that no longer exist.
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
- final ArrayMap<String, File> expectingBetter = new ArrayMap<>();
if (!mOnlyCore) {
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
@@ -2086,7 +2092,7 @@
+ ", versionCode=" + ps.versionCode + "; scanned versionCode="
+ scannedPkg.mVersionCode);
removePackageLI(ps, true);
- expectingBetter.put(ps.name, ps.codePath);
+ mExpectingBetter.put(ps.name, ps.codePath);
}
continue;
@@ -2160,10 +2166,10 @@
* the userdata partition actually showed up. If they never
* appeared, crawl back and revive the system version.
*/
- for (int i = 0; i < expectingBetter.size(); i++) {
- final String packageName = expectingBetter.keyAt(i);
+ for (int i = 0; i < mExpectingBetter.size(); i++) {
+ final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
- final File scanFile = expectingBetter.valueAt(i);
+ final File scanFile = mExpectingBetter.valueAt(i);
logCriticalInfo(Log.WARN, "Expected better " + packageName
+ " but never showed up; reverting to system");
@@ -2198,6 +2204,7 @@
}
}
}
+ mExpectingBetter.clear();
// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
@@ -5633,7 +5640,7 @@
if (pkg.mVersionCode <= ps.versionCode) {
// The system package has been updated and the code path does not match
// Ignore entry. Skip it.
- Slog.i(TAG, "Package " + ps.name + " at " + scanFile
+ if (DEBUG_INSTALL) Slog.i(TAG, "Package " + ps.name + " at " + scanFile
+ " ignored: updated version " + ps.versionCode
+ " better than this " + pkg.mVersionCode);
if (!updatedPkg.codePath.equals(scanFile)) {
@@ -5646,7 +5653,10 @@
updatedPkg.resourcePathString = scanFile.toString();
}
updatedPkg.pkg = pkg;
- throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, null);
+ throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
+ "Package " + ps.name + " at " + scanFile
+ + " ignored: updated version " + ps.versionCode
+ + " better than this " + pkg.mVersionCode);
} else {
// The current app on the system partition is better than
// what we have updated to on the data partition; switch
@@ -6429,20 +6439,29 @@
// scanned APK is both already known and at the path previously established
// for it. Previously unknown packages we pick up normally, but if we have an
// a priori expectation about this package's install presence, enforce it.
+ // With a singular exception for new system packages. When an OTA contains
+ // a new system package, we allow the codepath to change from a system location
+ // to the user-installed location. If we don't allow this change, any newer,
+ // user-installed version of the application will be ignored.
if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) {
- PackageSetting known = mSettings.peekPackageLPr(pkg.packageName);
- if (known != null) {
- if (DEBUG_PACKAGE_SCANNING) {
- Log.d(TAG, "Examining " + pkg.codePath
- + " and requiring known paths " + known.codePathString
- + " & " + known.resourcePathString);
- }
- if (!pkg.applicationInfo.getCodePath().equals(known.codePathString)
- || !pkg.applicationInfo.getResourcePath().equals(known.resourcePathString)) {
- throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
- "Application package " + pkg.packageName
- + " found at " + pkg.applicationInfo.getCodePath()
- + " but expected at " + known.codePathString + "; ignoring.");
+ if (mExpectingBetter.containsKey(pkg.packageName)) {
+ logCriticalInfo(Log.WARN,
+ "Relax SCAN_REQUIRE_KNOWN requirement for package " + pkg.packageName);
+ } else {
+ PackageSetting known = mSettings.peekPackageLPr(pkg.packageName);
+ if (known != null) {
+ if (DEBUG_PACKAGE_SCANNING) {
+ Log.d(TAG, "Examining " + pkg.codePath
+ + " and requiring known paths " + known.codePathString
+ + " & " + known.resourcePathString);
+ }
+ if (!pkg.applicationInfo.getCodePath().equals(known.codePathString)
+ || !pkg.applicationInfo.getResourcePath().equals(known.resourcePathString)) {
+ throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
+ "Application package " + pkg.packageName
+ + " found at " + pkg.applicationInfo.getCodePath()
+ + " but expected at " + known.codePathString + "; ignoring.");
+ }
}
}
}