summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/PackageManagerBackupAgent.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/PackageManagerBackupAgent.java')
-rw-r--r--services/java/com/android/server/PackageManagerBackupAgent.java227
1 files changed, 143 insertions, 84 deletions
diff --git a/services/java/com/android/server/PackageManagerBackupAgent.java b/services/java/com/android/server/PackageManagerBackupAgent.java
index cc84430..9422878 100644
--- a/services/java/com/android/server/PackageManagerBackupAgent.java
+++ b/services/java/com/android/server/PackageManagerBackupAgent.java
@@ -24,6 +24,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
+import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.util.Log;
@@ -52,6 +53,10 @@ public class PackageManagerBackupAgent extends BackupAgent {
private static final String TAG = "PMBA";
private static final boolean DEBUG = true;
+ // key under which we store global metadata (individual app metadata
+ // is stored using the package name as a key)
+ private static final String GLOBAL_METADATA_KEY = "@meta@";
+
private List<ApplicationInfo> mAllApps;
private PackageManager mPackageManager;
private HashMap<String, Metadata> mRestoredSignatures;
@@ -76,6 +81,7 @@ public class PackageManagerBackupAgent extends BackupAgent {
public Metadata getRestoredMetadata(String packageName) {
if (mRestoredSignatures == null) {
+ Log.w(TAG, "getRestoredMetadata() before metadata read!");
return null;
}
@@ -86,74 +92,97 @@ public class PackageManagerBackupAgent extends BackupAgent {
// the package name.
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) {
- HashSet<String> existing = parseStateFile(oldState);
-
- // For each app we have on device, see if we've backed it up yet. If not,
- // write its signature block to the output, keyed on the package name.
if (DEBUG) Log.v(TAG, "onBackup()");
+
ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); // we'll reuse these
DataOutputStream outWriter = new DataOutputStream(bufStream);
- for (ApplicationInfo app : mAllApps) {
- String packName = app.packageName;
- if (!existing.contains(packName)) {
- // We haven't stored this app's signatures yet, so we do that now
- try {
- PackageInfo info = mPackageManager.getPackageInfo(packName,
- PackageManager.GET_SIGNATURES);
- /*
- * Metadata for each package:
- *
- * int version -- [4] the package's versionCode
- * byte[] signatures -- [len] flattened Signature[] of the package
- */
-
- // marshall the version code in a canonical form
- bufStream.reset();
- outWriter.writeInt(info.versionCode);
- byte[] versionBuf = bufStream.toByteArray();
-
- byte[] sigs = flattenSignatureArray(info.signatures);
-
- // !!! TODO: take out this debugging
- if (DEBUG) {
- Log.v(TAG, "+ metadata for " + packName + " version=" + info.versionCode);
- }
- // Now we can write the backup entity for this package
- 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);
- } catch (IOException e) {
- // Real error writing data
- Log.e(TAG, "Unable to write package backup data file!");
- return;
- }
+ HashSet<String> existing = parseStateFile(oldState);
+
+ 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.
+ */
+ if (!existing.contains(GLOBAL_METADATA_KEY)) {
+ if (DEBUG) Log.v(TAG, "Storing global metadata key");
+ outWriter.writeInt(Build.VERSION.SDK_INT);
+ byte[] metadata = bufStream.toByteArray();
+ data.writeEntityHeader(GLOBAL_METADATA_KEY, metadata.length);
+ data.writeEntityData(metadata, metadata.length);
} 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!");
+ if (DEBUG) Log.v(TAG, "Global metadata key already stored");
+ }
+
+ // For each app we have on device, see if we've backed it up yet. If not,
+ // write its signature block to the output, keyed on the package name.
+ for (ApplicationInfo app : mAllApps) {
+ String packName = app.packageName;
+ if (!existing.contains(packName)) {
+ // We haven't stored this app's signatures yet, so we do that now
+ try {
+ PackageInfo info = mPackageManager.getPackageInfo(packName,
+ PackageManager.GET_SIGNATURES);
+ /*
+ * Metadata for each package:
+ *
+ * int version -- [4] the package's versionCode
+ * byte[] signatures -- [len] flattened Signature[] of the package
+ */
+
+ // marshall the version code in a canonical form
+ bufStream.reset();
+ outWriter.writeInt(info.versionCode);
+ byte[] versionBuf = bufStream.toByteArray();
+
+ byte[] sigs = flattenSignatureArray(info.signatures);
+
+ // !!! TODO: take out this debugging
+ if (DEBUG) {
+ Log.v(TAG, "+ metadata for " + packName
+ + " version=" + info.versionCode
+ + " versionLen=" + versionBuf.length
+ + " sigsLen=" + sigs.length);
+ }
+ // Now we can write the backup entity for this package
+ 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!");
+ }
}
}
- }
- // 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) {
- // !!! TODO: take out this msg
- if (DEBUG) Log.v(TAG, "- removing metadata for deleted pkg " + app);
- try {
- data.writeEntityHeader(app, -1);
- } catch (IOException e) {
- Log.e(TAG, "Unable to write package deletions!");
- return;
+ // 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) {
+ // !!! TODO: take out this msg
+ if (DEBUG) Log.v(TAG, "- removing metadata for deleted pkg " + app);
+ try {
+ data.writeEntityHeader(app, -1);
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to write package deletions!");
+ return;
+ }
}
+ } catch (IOException e) {
+ // Real error writing data
+ Log.e(TAG, "Unable to write package backup data file!");
+ return;
}
// Finally, write the new state blob -- just the list of all apps we handled
@@ -167,30 +196,53 @@ public class PackageManagerBackupAgent extends BackupAgent {
throws IOException {
List<ApplicationInfo> restoredApps = new ArrayList<ApplicationInfo>();
HashMap<String, Metadata> sigMap = new HashMap<String, Metadata>();
+ if (DEBUG) Log.v(TAG, "onRestore()");
+ int storedSystemVersion = -1;
while (data.readNextHeader()) {
+ String key = data.getKey();
int dataSize = data.getDataSize();
- byte[] buf = new byte[dataSize];
- data.readEntityData(buf, 0, dataSize);
-
- ByteArrayInputStream bufStream = new ByteArrayInputStream(buf);
- DataInputStream in = new DataInputStream(bufStream);
- int versionCode = in.readInt();
-
- Signature[] sigs = unflattenSignatureArray(in);
- String pkg = data.getKey();
-// !!! TODO: take out this debugging
- if (DEBUG) {
- Log.i(TAG, "+ restored metadata for " + pkg
- + " versionCode=" + versionCode + " sigs=" + sigs);
- }
- ApplicationInfo app = new ApplicationInfo();
- app.packageName = pkg;
- restoredApps.add(app);
- sigMap.put(pkg, new Metadata(versionCode, sigs));
+ if (DEBUG) Log.v(TAG, " got key=" + key + " dataSize=" + dataSize);
+
+ // generic setup to parse any entity data
+ byte[] dataBuf = new byte[dataSize];
+ data.readEntityData(dataBuf, 0, dataSize);
+ ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
+ DataInputStream in = new DataInputStream(baStream);
+
+ if (key.equals(GLOBAL_METADATA_KEY)) {
+ storedSystemVersion = 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;
+ }
+ // !!! TODO: remove this debugging output
+ if (DEBUG) {
+ Log.i(TAG, "Restore set version " + storedSystemVersion
+ + " is compatible with OS version " + Build.VERSION.SDK_INT);
+ }
+ } else {
+ // it's a file metadata record
+ int versionCode = in.readInt();
+ Signature[] sigs = unflattenSignatureArray(in);
+// !!! TODO: take out this debugging
+ if (DEBUG) {
+ Log.i(TAG, " restored metadata for " + key
+ + " dataSize=" + dataSize
+ + " versionCode=" + versionCode + " sigs=" + sigs);
+ }
+
+ ApplicationInfo app = new ApplicationInfo();
+ app.packageName = key;
+ restoredApps.add(app);
+ sigMap.put(key, new Metadata(versionCode, sigs));
+ }
}
+ // On successful completion, cache the signature map for the Backup Manager to use
mRestoredSignatures = sigMap;
}
@@ -225,6 +277,7 @@ public class PackageManagerBackupAgent extends BackupAgent {
try {
int num = in.readInt();
+ Log.v(TAG, " ... unflatten read " + num);
sigs = new Signature[num];
for (int i = 0; i < num; i++) {
int len = in.readInt();
@@ -273,20 +326,26 @@ public class PackageManagerBackupAgent extends BackupAgent {
return set;
}
- // Util: write a set of names into a new state file
+ // Util: write out our new backup state file
private void writeStateFile(List<ApplicationInfo> apps, ParcelFileDescriptor stateFile) {
FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor());
DataOutputStream out = new DataOutputStream(outstream);
- for (ApplicationInfo app : apps) {
- try {
+ 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);
+
+ // now write all the app names too
+ for (ApplicationInfo app : apps) {
byte[] pkgNameBuf = app.packageName.getBytes();
out.writeInt(pkgNameBuf.length);
out.write(pkgNameBuf);
- } catch (IOException e) {
- Log.e(TAG, "Unable to write package manager state file!");
- return;
}
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to write package manager state file!");
+ return;
}
}
}