summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2014-10-05 14:12:42 -0700
committerJeff Sharkey <jsharkey@android.com>2014-10-05 14:12:45 -0700
commit1c133105774835deaa99db78d9668b107246abef (patch)
tree472842fb4bb47f4987725504efcdea0e1f640c41 /services
parent914bd793b3415a198d0cb4216ff9da0a184ab803 (diff)
downloadframeworks_base-1c133105774835deaa99db78d9668b107246abef.zip
frameworks_base-1c133105774835deaa99db78d9668b107246abef.tar.gz
frameworks_base-1c133105774835deaa99db78d9668b107246abef.tar.bz2
Recover from missing upgrade to system package.
When a system app has been upgraded, we mark the built-in version as disabled, and skip it when parsing built-in apps, since we expect the userdata version to be scanned a few moments later. However, in very rare cases we can end up missing the expected userdata version, and we'd end up dropping the package entirely, even though we have a built-in version to fall back to. This change handles that case by rescanning and enabling the built-in version when the userdata version never materializes. Also include critical log messages in check-in dumpsys to help track down how we ended up in this state. Bug: 17805839 Change-Id: I9971f882f9bb8ab7934c20b04e0b72366c4d04d0
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java65
1 files changed, 64 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d90be0b..05f2d4a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -175,11 +175,13 @@ import android.view.Display;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
@@ -1553,6 +1555,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// 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()) {
@@ -1585,6 +1588,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+ ", versionCode=" + ps.versionCode + "; scanned versionCode="
+ scannedPkg.mVersionCode);
removePackageLI(ps, true);
+ expectingBetter.put(ps.name, ps.codePath);
}
continue;
@@ -1652,6 +1656,49 @@ public class PackageManagerService extends IPackageManager.Stub {
}
logCriticalInfo(Log.WARN, msg);
}
+
+ /**
+ * Make sure all system apps that we expected to appear on
+ * 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);
+ if (!mPackages.containsKey(packageName)) {
+ final File scanFile = expectingBetter.valueAt(i);
+
+ logCriticalInfo(Log.WARN, "Expected better " + packageName
+ + " but never showed up; reverting to system");
+
+ final int reparseFlags;
+ if (FileUtils.contains(privilegedAppDir, scanFile)) {
+ reparseFlags = PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR
+ | PackageParser.PARSE_IS_PRIVILEGED;
+ } else if (FileUtils.contains(systemAppDir, scanFile)) {
+ reparseFlags = PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR;
+ } else if (FileUtils.contains(vendorAppDir, scanFile)) {
+ reparseFlags = PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR;
+ } else if (FileUtils.contains(oemAppDir, scanFile)) {
+ reparseFlags = PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR;
+ } else {
+ Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
+ continue;
+ }
+
+ mSettings.enableSystemPackageLPw(packageName);
+
+ try {
+ scanPackageLI(scanFile, reparseFlags, scanFlags, 0, null);
+ } catch (PackageManagerException e) {
+ Slog.e(TAG, "Failed to parse original system package: "
+ + e.getMessage());
+ }
+ }
+ }
}
// Now that we know all of the shared libraries, update all clients to have
@@ -4195,7 +4242,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
- + "reverting from " + ps.codePathString
+ + " reverting from " + ps.codePathString
+ ": new version " + pkg.mVersionCode
+ " better than installed " + ps.versionCode);
@@ -12084,6 +12131,7 @@ public class PackageManagerService extends IPackageManager.Stub {
break;
}
opti++;
+
if ("-a".equals(opt)) {
// Right now we only know how to print all.
} else if ("-h".equals(opt)) {
@@ -12430,6 +12478,21 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
}
+
+ if (checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES)) {
+ BufferedReader in = null;
+ String line = null;
+ try {
+ in = new BufferedReader(new FileReader(getSettingsProblemFile()));
+ while ((line = in.readLine()) != null) {
+ pw.print("msg,");
+ pw.println(line);
+ }
+ } catch (IOException ignored) {
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
}
}