Loading services/java/com/android/server/BackupManagerService.java +28 −21 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import com.android.internal.backup.LocalTransport; import com.android.internal.backup.IBackupTransport; import com.android.server.PackageManagerBackupAgent; import com.android.server.PackageManagerBackupAgent.Metadata; import java.io.EOFException; import java.io.File; Loading Loading @@ -111,9 +112,8 @@ class BackupManagerService extends IBackupManager.Stub { // Do we need to back up the package manager metadata on the next pass? private boolean mDoPackageManager; private static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; // Backups that we have started. These are separate to prevent starvation // if an app keeps re-enqueuing itself. private ArrayList<BackupRequest> mBackupQueue; // locking around the pending-backup management private final Object mQueueLock = new Object(); // The thread performing the sequence of queued backups binds to each app's agent Loading Loading @@ -296,6 +296,7 @@ class BackupManagerService extends IBackupManager.Stub { } // snapshot the pending-backup set and work on that ArrayList<BackupRequest> queue = new ArrayList<BackupRequest>(); File oldJournal = mJournal; synchronized (mQueueLock) { if (mPendingBackups.size() == 0) { Loading @@ -303,13 +304,11 @@ class BackupManagerService extends IBackupManager.Stub { break; } if (mBackupQueue == null) { mBackupQueue = new ArrayList<BackupRequest>(); for (BackupRequest b: mPendingBackups.values()) { mBackupQueue.add(b); } mPendingBackups = new HashMap<ApplicationInfo,BackupRequest>(); queue.add(b); } Log.v(TAG, "clearing pending backups"); mPendingBackups.clear(); // Start a new backup-queue journal file too if (mJournalStream != null) { Loading @@ -328,7 +327,7 @@ class BackupManagerService extends IBackupManager.Stub { // at next boot and the journaled requests fulfilled. } (new PerformBackupThread(transport, mBackupQueue, oldJournal)).start(); (new PerformBackupThread(transport, queue, oldJournal)).start(); break; } Loading Loading @@ -759,6 +758,8 @@ class BackupManagerService extends IBackupManager.Stub { private boolean signaturesMatch(Signature[] storedSigs, Signature[] deviceSigs) { // Allow unsigned apps, but not signed on one device and unsigned on the other // !!! TODO: is this the right policy? if (DEBUG) Log.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceSigs); if ((storedSigs == null || storedSigs.length == 0) && (deviceSigs == null || deviceSigs.length == 0)) { return true; Loading Loading @@ -800,6 +801,7 @@ class BackupManagerService extends IBackupManager.Stub { @Override public void run() { if (DEBUG) Log.v(TAG, "Beginning restore process"); /** * Restore sequence: * Loading Loading @@ -847,13 +849,19 @@ class BackupManagerService extends IBackupManager.Stub { PackageInfo app = isRestorable(pkg); if (app != null) { // Validate against the backed-up signature block, too Signature[] storedSigs = pmAgent.getRestoredSignatures(app.packageName); // !!! TODO: check app version here as well if (signaturesMatch(storedSigs, app.signatures)) { Metadata info = pmAgent.getRestoredMetadata(app.packageName); if (app.versionCode >= info.versionCode) { if (DEBUG) Log.v(TAG, "Restore version " + info.versionCode + " compatible with app version " + app.versionCode); if (signaturesMatch(info.signatures, app.signatures)) { appsToRestore.add(app); } else { Log.w(TAG, "Sig mismatch on restore of " + app.packageName); Log.w(TAG, "Sig mismatch restoring " + app.packageName); } } else { Log.i(TAG, "Restore set for " + app.packageName + " is too new [" + info.versionCode + "] for installed app version " + app.versionCode); } } } Loading Loading @@ -1202,11 +1210,10 @@ class BackupManagerService extends IBackupManager.Stub { pw.println(app.toString()); } } pw.println("Pending:"); Iterator<BackupRequest> br = mPendingBackups.values().iterator(); while (br.hasNext()) { pw.println("Pending: " + mPendingBackups.size()); for (BackupRequest req : mPendingBackups.values()) { pw.print(" "); pw.println(br); pw.println(req); } } } Loading services/java/com/android/server/PackageManagerBackupAgent.java +47 −22 Original line number Diff line number Diff line Loading @@ -40,9 +40,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; // !!!TODO: take this out import java.util.zip.CRC32; /** * We back up the signatures of each package so that during a system restore, * we can verify that the app whose data we think we have matches the app Loading @@ -57,7 +54,17 @@ public class PackageManagerBackupAgent extends BackupAgent { private List<ApplicationInfo> mAllApps; private PackageManager mPackageManager; private HashMap<String, Signature[]> mRestoredSignatures; private HashMap<String, Metadata> mRestoredSignatures; public class Metadata { public int versionCode; public Signature[] signatures; Metadata(int version, Signature[] sigs) { versionCode = version; signatures = sigs; } } // We're constructed with the set of applications that are participating // in backup. This set changes as apps are installed & removed. Loading @@ -67,7 +74,7 @@ public class PackageManagerBackupAgent extends BackupAgent { mRestoredSignatures = null; } public Signature[] getRestoredSignatures(String packageName) { public Metadata getRestoredMetadata(String packageName) { if (mRestoredSignatures == null) { return null; } Loading @@ -83,6 +90,9 @@ public class PackageManagerBackupAgent extends BackupAgent { // 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)) { Loading @@ -90,16 +100,27 @@ public class PackageManagerBackupAgent extends BackupAgent { try { PackageInfo info = mPackageManager.getPackageInfo(packName, PackageManager.GET_SIGNATURES); // build a byte array out of the signature list /* * 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) { CRC32 crc = new CRC32(); crc.update(sigs); Log.i(TAG, "+ flat sig array for " + packName + " : " + crc.getValue()); Log.v(TAG, "+ metadata for " + packName + " version=" + info.versionCode); } data.writeEntityHeader(packName, 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. Loading @@ -113,6 +134,8 @@ public class PackageManagerBackupAgent extends BackupAgent { } 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!"); } Loading @@ -123,6 +146,8 @@ public class PackageManagerBackupAgent extends BackupAgent { // 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) { Loading @@ -141,27 +166,29 @@ public class PackageManagerBackupAgent extends BackupAgent { public void onRestore(BackupDataInput data, ParcelFileDescriptor newState) throws IOException { List<ApplicationInfo> restoredApps = new ArrayList<ApplicationInfo>(); HashMap<String, Signature[]> sigMap = new HashMap<String, Signature[]>(); HashMap<String, Metadata> sigMap = new HashMap<String, Metadata>(); while (data.readNextHeader()) { int dataSize = data.getDataSize(); byte[] buf = new byte[dataSize]; data.readEntityData(buf, 0, dataSize); Signature[] sigs = unflattenSignatureArray(buf); 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) { CRC32 crc = new CRC32(); crc.update(buf); Log.i(TAG, "- unflat sig array for " + pkg + " : " + crc.getValue()); Log.i(TAG, "+ restored metadata for " + pkg + " versionCode=" + versionCode + " sigs=" + sigs); } ApplicationInfo app = new ApplicationInfo(); app.packageName = pkg; restoredApps.add(app); sigMap.put(pkg, sigs); sigMap.put(pkg, new Metadata(versionCode, sigs)); } mRestoredSignatures = sigMap; Loading Loading @@ -193,9 +220,7 @@ public class PackageManagerBackupAgent extends BackupAgent { return outBuf.toByteArray(); } private Signature[] unflattenSignatureArray(byte[] buffer) { ByteArrayInputStream inBufStream = new ByteArrayInputStream(buffer); DataInputStream in = new DataInputStream(inBufStream); private Signature[] unflattenSignatureArray(/*byte[] buffer*/ DataInputStream in) { Signature[] sigs = null; try { Loading Loading
services/java/com/android/server/BackupManagerService.java +28 −21 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import com.android.internal.backup.LocalTransport; import com.android.internal.backup.IBackupTransport; import com.android.server.PackageManagerBackupAgent; import com.android.server.PackageManagerBackupAgent.Metadata; import java.io.EOFException; import java.io.File; Loading Loading @@ -111,9 +112,8 @@ class BackupManagerService extends IBackupManager.Stub { // Do we need to back up the package manager metadata on the next pass? private boolean mDoPackageManager; private static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; // Backups that we have started. These are separate to prevent starvation // if an app keeps re-enqueuing itself. private ArrayList<BackupRequest> mBackupQueue; // locking around the pending-backup management private final Object mQueueLock = new Object(); // The thread performing the sequence of queued backups binds to each app's agent Loading Loading @@ -296,6 +296,7 @@ class BackupManagerService extends IBackupManager.Stub { } // snapshot the pending-backup set and work on that ArrayList<BackupRequest> queue = new ArrayList<BackupRequest>(); File oldJournal = mJournal; synchronized (mQueueLock) { if (mPendingBackups.size() == 0) { Loading @@ -303,13 +304,11 @@ class BackupManagerService extends IBackupManager.Stub { break; } if (mBackupQueue == null) { mBackupQueue = new ArrayList<BackupRequest>(); for (BackupRequest b: mPendingBackups.values()) { mBackupQueue.add(b); } mPendingBackups = new HashMap<ApplicationInfo,BackupRequest>(); queue.add(b); } Log.v(TAG, "clearing pending backups"); mPendingBackups.clear(); // Start a new backup-queue journal file too if (mJournalStream != null) { Loading @@ -328,7 +327,7 @@ class BackupManagerService extends IBackupManager.Stub { // at next boot and the journaled requests fulfilled. } (new PerformBackupThread(transport, mBackupQueue, oldJournal)).start(); (new PerformBackupThread(transport, queue, oldJournal)).start(); break; } Loading Loading @@ -759,6 +758,8 @@ class BackupManagerService extends IBackupManager.Stub { private boolean signaturesMatch(Signature[] storedSigs, Signature[] deviceSigs) { // Allow unsigned apps, but not signed on one device and unsigned on the other // !!! TODO: is this the right policy? if (DEBUG) Log.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device=" + deviceSigs); if ((storedSigs == null || storedSigs.length == 0) && (deviceSigs == null || deviceSigs.length == 0)) { return true; Loading Loading @@ -800,6 +801,7 @@ class BackupManagerService extends IBackupManager.Stub { @Override public void run() { if (DEBUG) Log.v(TAG, "Beginning restore process"); /** * Restore sequence: * Loading Loading @@ -847,13 +849,19 @@ class BackupManagerService extends IBackupManager.Stub { PackageInfo app = isRestorable(pkg); if (app != null) { // Validate against the backed-up signature block, too Signature[] storedSigs = pmAgent.getRestoredSignatures(app.packageName); // !!! TODO: check app version here as well if (signaturesMatch(storedSigs, app.signatures)) { Metadata info = pmAgent.getRestoredMetadata(app.packageName); if (app.versionCode >= info.versionCode) { if (DEBUG) Log.v(TAG, "Restore version " + info.versionCode + " compatible with app version " + app.versionCode); if (signaturesMatch(info.signatures, app.signatures)) { appsToRestore.add(app); } else { Log.w(TAG, "Sig mismatch on restore of " + app.packageName); Log.w(TAG, "Sig mismatch restoring " + app.packageName); } } else { Log.i(TAG, "Restore set for " + app.packageName + " is too new [" + info.versionCode + "] for installed app version " + app.versionCode); } } } Loading Loading @@ -1202,11 +1210,10 @@ class BackupManagerService extends IBackupManager.Stub { pw.println(app.toString()); } } pw.println("Pending:"); Iterator<BackupRequest> br = mPendingBackups.values().iterator(); while (br.hasNext()) { pw.println("Pending: " + mPendingBackups.size()); for (BackupRequest req : mPendingBackups.values()) { pw.print(" "); pw.println(br); pw.println(req); } } } Loading
services/java/com/android/server/PackageManagerBackupAgent.java +47 −22 Original line number Diff line number Diff line Loading @@ -40,9 +40,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; // !!!TODO: take this out import java.util.zip.CRC32; /** * We back up the signatures of each package so that during a system restore, * we can verify that the app whose data we think we have matches the app Loading @@ -57,7 +54,17 @@ public class PackageManagerBackupAgent extends BackupAgent { private List<ApplicationInfo> mAllApps; private PackageManager mPackageManager; private HashMap<String, Signature[]> mRestoredSignatures; private HashMap<String, Metadata> mRestoredSignatures; public class Metadata { public int versionCode; public Signature[] signatures; Metadata(int version, Signature[] sigs) { versionCode = version; signatures = sigs; } } // We're constructed with the set of applications that are participating // in backup. This set changes as apps are installed & removed. Loading @@ -67,7 +74,7 @@ public class PackageManagerBackupAgent extends BackupAgent { mRestoredSignatures = null; } public Signature[] getRestoredSignatures(String packageName) { public Metadata getRestoredMetadata(String packageName) { if (mRestoredSignatures == null) { return null; } Loading @@ -83,6 +90,9 @@ public class PackageManagerBackupAgent extends BackupAgent { // 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)) { Loading @@ -90,16 +100,27 @@ public class PackageManagerBackupAgent extends BackupAgent { try { PackageInfo info = mPackageManager.getPackageInfo(packName, PackageManager.GET_SIGNATURES); // build a byte array out of the signature list /* * 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) { CRC32 crc = new CRC32(); crc.update(sigs); Log.i(TAG, "+ flat sig array for " + packName + " : " + crc.getValue()); Log.v(TAG, "+ metadata for " + packName + " version=" + info.versionCode); } data.writeEntityHeader(packName, 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. Loading @@ -113,6 +134,8 @@ public class PackageManagerBackupAgent extends BackupAgent { } 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!"); } Loading @@ -123,6 +146,8 @@ public class PackageManagerBackupAgent extends BackupAgent { // 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) { Loading @@ -141,27 +166,29 @@ public class PackageManagerBackupAgent extends BackupAgent { public void onRestore(BackupDataInput data, ParcelFileDescriptor newState) throws IOException { List<ApplicationInfo> restoredApps = new ArrayList<ApplicationInfo>(); HashMap<String, Signature[]> sigMap = new HashMap<String, Signature[]>(); HashMap<String, Metadata> sigMap = new HashMap<String, Metadata>(); while (data.readNextHeader()) { int dataSize = data.getDataSize(); byte[] buf = new byte[dataSize]; data.readEntityData(buf, 0, dataSize); Signature[] sigs = unflattenSignatureArray(buf); 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) { CRC32 crc = new CRC32(); crc.update(buf); Log.i(TAG, "- unflat sig array for " + pkg + " : " + crc.getValue()); Log.i(TAG, "+ restored metadata for " + pkg + " versionCode=" + versionCode + " sigs=" + sigs); } ApplicationInfo app = new ApplicationInfo(); app.packageName = pkg; restoredApps.add(app); sigMap.put(pkg, sigs); sigMap.put(pkg, new Metadata(versionCode, sigs)); } mRestoredSignatures = sigMap; Loading Loading @@ -193,9 +220,7 @@ public class PackageManagerBackupAgent extends BackupAgent { return outBuf.toByteArray(); } private Signature[] unflattenSignatureArray(byte[] buffer) { ByteArrayInputStream inBufStream = new ByteArrayInputStream(buffer); DataInputStream in = new DataInputStream(inBufStream); private Signature[] unflattenSignatureArray(/*byte[] buffer*/ DataInputStream in) { Signature[] sigs = null; try { Loading