summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Tate <ctate@google.com>2009-07-01 16:01:48 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-07-01 16:01:48 -0700
commit3b0b1a11d6491385bea6cfe9b3adfe8da1aca88c (patch)
tree50ec73ae1f4d0aea51bb18744ff65fe65a44ccfd
parent0901c82336c79ca3e3d67b1df8a5cb7ee45ec13e (diff)
parent72d19aa51e90d45c7895629db78e548da2f6d469 (diff)
downloadframeworks_base-3b0b1a11d6491385bea6cfe9b3adfe8da1aca88c.zip
frameworks_base-3b0b1a11d6491385bea6cfe9b3adfe8da1aca88c.tar.gz
frameworks_base-3b0b1a11d6491385bea6cfe9b3adfe8da1aca88c.tar.bz2
am 72d19aa5: Tighten up the metadata backup logic
Merge commit '72d19aa51e90d45c7895629db78e548da2f6d469' * commit '72d19aa51e90d45c7895629db78e548da2f6d469': Tighten up the metadata backup logic
-rw-r--r--services/java/com/android/server/PackageManagerBackupAgent.java136
1 files changed, 94 insertions, 42 deletions
diff --git a/services/java/com/android/server/PackageManagerBackupAgent.java b/services/java/com/android/server/PackageManagerBackupAgent.java
index 16f14e8..a1b4c26 100644
--- a/services/java/com/android/server/PackageManagerBackupAgent.java
+++ b/services/java/com/android/server/PackageManagerBackupAgent.java
@@ -59,7 +59,14 @@ public class PackageManagerBackupAgent extends BackupAgent {
private List<PackageInfo> mAllPackages;
private PackageManager mPackageManager;
+ // version & signature info of each app in a restore set
private HashMap<String, Metadata> mRestoredSignatures;
+ // The version info of each backed-up app as read from the state file
+ private HashMap<String, Metadata> mStateVersions = new HashMap<String, Metadata>();
+
+ private final HashSet<String> mExisting = new HashSet<String>();
+ private int mStoredSdkVersion;
+ private String mStoredIncrementalVersion;
public class Metadata {
public int versionCode;
@@ -96,24 +103,39 @@ public class PackageManagerBackupAgent extends BackupAgent {
ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); // we'll reuse these
DataOutputStream outWriter = new DataOutputStream(bufStream);
- HashSet<String> existing = parseStateFile(oldState);
+ parseStateFile(oldState);
+
+ // If the stored version string differs, we need to re-backup all
+ // of the metadata. We force this by removing everything from the
+ // "already backed up" map built by parseStateFile().
+ if (mStoredIncrementalVersion == null
+ || !mStoredIncrementalVersion.equals(Build.VERSION.INCREMENTAL)) {
+ Log.i(TAG, "Previous metadata " + mStoredIncrementalVersion + " mismatch vs "
+ + Build.VERSION.INCREMENTAL + " - rewriting");
+ mExisting.clear();
+ }
try {
/*
* Global metadata:
*
- * int version -- the SDK version of the OS itself on the device
- * that produced this backup set. Used to reject
- * backups from later OSes onto earlier ones.
+ * int SDKversion -- the SDK version of the OS itself on the device
+ * that produced this backup set. Used to reject
+ * backups from later OSes onto earlier ones.
+ * String incremental -- the incremental release name of the OS stored in
+ * the backup set.
*/
- if (!existing.contains(GLOBAL_METADATA_KEY)) {
+ if (!mExisting.contains(GLOBAL_METADATA_KEY)) {
if (DEBUG) Log.v(TAG, "Storing global metadata key");
outWriter.writeInt(Build.VERSION.SDK_INT);
+ outWriter.writeUTF(Build.VERSION.INCREMENTAL);
byte[] metadata = bufStream.toByteArray();
data.writeEntityHeader(GLOBAL_METADATA_KEY, metadata.length);
data.writeEntityData(metadata, metadata.length);
} else {
if (DEBUG) Log.v(TAG, "Global metadata key already stored");
+ // don't consider it to have been skipped/deleted
+ mExisting.remove(GLOBAL_METADATA_KEY);
}
// For each app we have on device, see if we've backed it up yet. If not,
@@ -123,11 +145,36 @@ public class PackageManagerBackupAgent extends BackupAgent {
if (packName.equals(GLOBAL_METADATA_KEY)) {
// We've already handled the metadata key; skip it here
continue;
- } else if (!existing.contains(packName)) {
- // We haven't stored this app's signatures yet, so we do that now
+ } else {
+ PackageInfo info = null;
try {
- PackageInfo info = mPackageManager.getPackageInfo(packName,
+ info = mPackageManager.getPackageInfo(packName,
PackageManager.GET_SIGNATURES);
+ } catch (NameNotFoundException e) {
+ // Weird; we just found it, and now are told it doesn't exist.
+ // Treat it as having been removed from the device.
+ mExisting.add(packName);
+ continue;
+ }
+
+ boolean doBackup = false;
+ if (!mExisting.contains(packName)) {
+ // We haven't backed up this app before
+ doBackup = true;
+ } else {
+ // We *have* backed this one up before. Check whether the version
+ // of the backup matches the version of the current app; if they
+ // don't match, the app has been updated and we need to store its
+ // metadata again. In either case, take it out of mExisting so that
+ // we don't consider it deleted later.
+ if (info.versionCode != mStateVersions.get(packName).versionCode) {
+ doBackup = true;
+ }
+ mExisting.remove(packName);
+ }
+
+ if (doBackup) {
+ // We need to store this app's metadata
/*
* Metadata for each package:
*
@@ -135,7 +182,7 @@ public class PackageManagerBackupAgent extends BackupAgent {
* byte[] signatures -- [len] flattened Signature[] of the package
*/
- // marshall the version code in a canonical form
+ // marshal the version code in a canonical form
bufStream.reset();
outWriter.writeInt(info.versionCode);
byte[] versionBuf = bufStream.toByteArray();
@@ -153,18 +200,6 @@ public class PackageManagerBackupAgent extends BackupAgent {
data.writeEntityHeader(packName, versionBuf.length + sigs.length);
data.writeEntityData(versionBuf, versionBuf.length);
data.writeEntityData(sigs, sigs.length);
- } catch (NameNotFoundException e) {
- // Weird; we just found it, and now are told it doesn't exist.
- // Treat it as having been removed from the device.
- existing.add(packName);
- }
- } else {
- // We've already backed up this app. Remove it from the set so
- // we can tell at the end what has disappeared from the device.
- // !!! TODO: take out the debugging message
- if (DEBUG) Log.v(TAG, "= already backed up metadata for " + packName);
- if (!existing.remove(packName)) {
- Log.d(TAG, "*** failed to remove " + packName + " from package set!");
}
}
}
@@ -172,7 +207,7 @@ public class PackageManagerBackupAgent extends BackupAgent {
// At this point, the only entries in 'existing' are apps that were
// mentioned in the saved state file, but appear to no longer be present
// on the device. Write a deletion entity for them.
- for (String app : existing) {
+ for (String app : mExisting) {
// !!! TODO: take out this msg
if (DEBUG) Log.v(TAG, "- removing metadata for deleted pkg " + app);
try {
@@ -215,17 +250,21 @@ public class PackageManagerBackupAgent extends BackupAgent {
DataInputStream in = new DataInputStream(baStream);
if (key.equals(GLOBAL_METADATA_KEY)) {
- storedSystemVersion = in.readInt();
+ int storedSdkVersion = in.readInt();
if (DEBUG) Log.v(TAG, " storedSystemVersion = " + storedSystemVersion);
if (storedSystemVersion > Build.VERSION.SDK_INT) {
// returning before setting the sig map means we rejected the restore set
Log.w(TAG, "Restore set was from a later version of Android; not restoring");
return;
}
+ mStoredSdkVersion = storedSdkVersion;
+ mStoredIncrementalVersion = in.readUTF();
// !!! TODO: remove this debugging output
if (DEBUG) {
Log.i(TAG, "Restore set version " + storedSystemVersion
- + " is compatible with OS version " + Build.VERSION.SDK_INT);
+ + " is compatible with OS version " + Build.VERSION.SDK_INT
+ + " (" + mStoredIncrementalVersion + " vs "
+ + Build.VERSION.INCREMENTAL + ")");
}
} else {
// it's a file metadata record
@@ -302,31 +341,45 @@ public class PackageManagerBackupAgent extends BackupAgent {
}
// Util: parse out an existing state file into a usable structure
- private HashSet<String> parseStateFile(ParcelFileDescriptor stateFile) {
- HashSet<String> set = new HashSet<String>();
+ private void parseStateFile(ParcelFileDescriptor stateFile) {
+ mExisting.clear();
+ mStateVersions.clear();
+ mStoredSdkVersion = 0;
+ mStoredIncrementalVersion = null;
+
// The state file is just the list of app names we have stored signatures for
+ // with the exception of the metadata block, to which is also appended the
+ // version numbers corresponding with the last time we wrote this PM block.
+ // If they mismatch the current system, we'll re-store the metadata key.
FileInputStream instream = new FileInputStream(stateFile.getFileDescriptor());
DataInputStream in = new DataInputStream(instream);
int bufSize = 256;
byte[] buf = new byte[bufSize];
try {
- int nameSize = in.readInt();
- if (bufSize < nameSize) {
- bufSize = nameSize + 32;
- buf = new byte[bufSize];
+ String pkg = in.readUTF();
+ if (pkg.equals(GLOBAL_METADATA_KEY)) {
+ mStoredSdkVersion = in.readInt();
+ mStoredIncrementalVersion = in.readUTF();
+ mExisting.add(GLOBAL_METADATA_KEY);
+ } else {
+ Log.e(TAG, "No global metadata in state file!");
+ return;
+ }
+
+ // The global metadata was first; now read all the apps
+ while (true) {
+ pkg = in.readUTF();
+ int versionCode = in.readInt();
+ mExisting.add(pkg);
+ mStateVersions.put(pkg, new Metadata(versionCode, null));
}
- in.read(buf, 0, nameSize);
- String pkg = new String(buf, 0, nameSize);
- set.add(pkg);
} catch (EOFException eof) {
// safe; we're done
} catch (IOException e) {
// whoops, bad state file. abort.
- Log.e(TAG, "Unable to read Package Manager state file");
- return null;
+ Log.e(TAG, "Unable to read Package Manager state file: " + e);
}
- return set;
}
// Util: write out our new backup state file
@@ -336,15 +389,14 @@ public class PackageManagerBackupAgent extends BackupAgent {
try {
// by the time we get here we know we've stored the global metadata record
- byte[] metaNameBuf = GLOBAL_METADATA_KEY.getBytes();
- out.writeInt(metaNameBuf.length);
- out.write(metaNameBuf);
+ out.writeUTF(GLOBAL_METADATA_KEY);
+ out.writeInt(Build.VERSION.SDK_INT);
+ out.writeUTF(Build.VERSION.INCREMENTAL);
// now write all the app names too
for (PackageInfo pkg : pkgs) {
- byte[] pkgNameBuf = pkg.packageName.getBytes();
- out.writeInt(pkgNameBuf.length);
- out.write(pkgNameBuf);
+ out.writeUTF(pkg.packageName);
+ out.writeInt(pkg.versionCode);
}
} catch (IOException e) {
Log.e(TAG, "Unable to write package manager state file!");