Loading core/java/com/android/internal/backup/LocalTransport.java +14 −7 Original line number Diff line number Diff line Loading @@ -170,18 +170,13 @@ public class LocalTransport extends IBackupTransport.Stub { // The restore set is the concatenation of the individual record blobs, // each of which is a file in the package's directory File[] blobs = packageDir.listFiles(); if (DEBUG) Log.v(TAG, " found " + blobs.length + " key files"); int err = 0; if (blobs != null && blobs.length > 0) { BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor()); try { for (File f : blobs) { FileInputStream in = new FileInputStream(f); int size = (int) f.length(); byte[] buf = new byte[size]; in.read(buf); String key = new String(Base64.decode(f.getName())); out.writeEntityHeader(key, size); out.writeEntityData(buf, size); copyToRestoreData(f, out); } } catch (Exception e) { Log.e(TAG, "Unable to read backup records"); Loading @@ -190,4 +185,16 @@ public class LocalTransport extends IBackupTransport.Stub { } return err; } private void copyToRestoreData(File f, BackupDataOutput out) throws IOException { FileInputStream in = new FileInputStream(f); int size = (int) f.length(); byte[] buf = new byte[size]; in.read(buf); String key = new String(Base64.decode(f.getName())); if (DEBUG) Log.v(TAG, " ... copy to stream: key=" + key + " size=" + size); out.writeEntityHeader(key, size); out.writeEntityData(buf, size); } } services/java/com/android/server/BackupManagerService.java +19 −9 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.content.pm.PackageManager; import android.content.pm.Signature; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; Loading Loading @@ -850,18 +851,27 @@ class BackupManagerService extends IBackupManager.Stub { if (app != null) { // Validate against the backed-up signature block, too Metadata info = pmAgent.getRestoredMetadata(app.packageName); if (info != null) { if (app.versionCode >= info.versionCode) { if (DEBUG) Log.v(TAG, "Restore version " + info.versionCode + " compatible with app version " + app.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 restoring " + 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); + "] for installed app version " + app.versionCode); } } else { Log.d(TAG, "Unable to get metadata for " + app.packageName); } } } Loading services/java/com/android/server/PackageManagerBackupAgent.java +143 −84 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; } Loading @@ -86,13 +92,32 @@ public class PackageManagerBackupAgent extends BackupAgent { // the package name. public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) { if (DEBUG) Log.v(TAG, "onBackup()"); ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); // we'll reuse these DataOutputStream outWriter = new DataOutputStream(bufStream); 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 { 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. 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 @@ -116,7 +141,10 @@ public class PackageManagerBackupAgent extends BackupAgent { // !!! TODO: take out this debugging if (DEBUG) { Log.v(TAG, "+ metadata for " + packName + " version=" + info.versionCode); 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); Loading @@ -126,10 +154,6 @@ public class PackageManagerBackupAgent extends BackupAgent { // 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; } } else { // We've already backed up this app. Remove it from the set so Loading @@ -155,6 +179,11 @@ public class PackageManagerBackupAgent extends BackupAgent { 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 writeStateFile(mAllApps, newState); Loading @@ -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(); 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); String pkg = data.getKey(); // !!! TODO: take out this debugging if (DEBUG) { Log.i(TAG, "+ restored metadata for " + pkg Log.i(TAG, " restored metadata for " + key + " dataSize=" + dataSize + " versionCode=" + versionCode + " sigs=" + sigs); } ApplicationInfo app = new ApplicationInfo(); app.packageName = pkg; app.packageName = key; restoredApps.add(app); sigMap.put(pkg, new Metadata(versionCode, sigs)); sigMap.put(key, new Metadata(versionCode, sigs)); } } // On successful completion, cache the signature map for the Backup Manager to use mRestoredSignatures = sigMap; } Loading Loading @@ -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(); Loading Loading @@ -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 { // 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; } } } } Loading
core/java/com/android/internal/backup/LocalTransport.java +14 −7 Original line number Diff line number Diff line Loading @@ -170,18 +170,13 @@ public class LocalTransport extends IBackupTransport.Stub { // The restore set is the concatenation of the individual record blobs, // each of which is a file in the package's directory File[] blobs = packageDir.listFiles(); if (DEBUG) Log.v(TAG, " found " + blobs.length + " key files"); int err = 0; if (blobs != null && blobs.length > 0) { BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor()); try { for (File f : blobs) { FileInputStream in = new FileInputStream(f); int size = (int) f.length(); byte[] buf = new byte[size]; in.read(buf); String key = new String(Base64.decode(f.getName())); out.writeEntityHeader(key, size); out.writeEntityData(buf, size); copyToRestoreData(f, out); } } catch (Exception e) { Log.e(TAG, "Unable to read backup records"); Loading @@ -190,4 +185,16 @@ public class LocalTransport extends IBackupTransport.Stub { } return err; } private void copyToRestoreData(File f, BackupDataOutput out) throws IOException { FileInputStream in = new FileInputStream(f); int size = (int) f.length(); byte[] buf = new byte[size]; in.read(buf); String key = new String(Base64.decode(f.getName())); if (DEBUG) Log.v(TAG, " ... copy to stream: key=" + key + " size=" + size); out.writeEntityHeader(key, size); out.writeEntityData(buf, size); } }
services/java/com/android/server/BackupManagerService.java +19 −9 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.content.pm.PackageManager; import android.content.pm.Signature; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; Loading Loading @@ -850,18 +851,27 @@ class BackupManagerService extends IBackupManager.Stub { if (app != null) { // Validate against the backed-up signature block, too Metadata info = pmAgent.getRestoredMetadata(app.packageName); if (info != null) { if (app.versionCode >= info.versionCode) { if (DEBUG) Log.v(TAG, "Restore version " + info.versionCode + " compatible with app version " + app.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 restoring " + 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); + "] for installed app version " + app.versionCode); } } else { Log.d(TAG, "Unable to get metadata for " + app.packageName); } } } Loading
services/java/com/android/server/PackageManagerBackupAgent.java +143 −84 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; } Loading @@ -86,13 +92,32 @@ public class PackageManagerBackupAgent extends BackupAgent { // the package name. public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) { if (DEBUG) Log.v(TAG, "onBackup()"); ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); // we'll reuse these DataOutputStream outWriter = new DataOutputStream(bufStream); 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 { 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. 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 @@ -116,7 +141,10 @@ public class PackageManagerBackupAgent extends BackupAgent { // !!! TODO: take out this debugging if (DEBUG) { Log.v(TAG, "+ metadata for " + packName + " version=" + info.versionCode); 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); Loading @@ -126,10 +154,6 @@ public class PackageManagerBackupAgent extends BackupAgent { // 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; } } else { // We've already backed up this app. Remove it from the set so Loading @@ -155,6 +179,11 @@ public class PackageManagerBackupAgent extends BackupAgent { 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 writeStateFile(mAllApps, newState); Loading @@ -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(); 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); String pkg = data.getKey(); // !!! TODO: take out this debugging if (DEBUG) { Log.i(TAG, "+ restored metadata for " + pkg Log.i(TAG, " restored metadata for " + key + " dataSize=" + dataSize + " versionCode=" + versionCode + " sigs=" + sigs); } ApplicationInfo app = new ApplicationInfo(); app.packageName = pkg; app.packageName = key; restoredApps.add(app); sigMap.put(pkg, new Metadata(versionCode, sigs)); sigMap.put(key, new Metadata(versionCode, sigs)); } } // On successful completion, cache the signature map for the Backup Manager to use mRestoredSignatures = sigMap; } Loading Loading @@ -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(); Loading Loading @@ -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 { // 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; } } } }