Loading services/java/com/android/server/PackageManagerBackupAgent.java +83 −89 Original line number Diff line number Diff line Loading @@ -122,8 +122,8 @@ public class PackageManagerBackupAgent extends BackupAgent { ParcelFileDescriptor newState) { if (DEBUG) Slog.v(TAG, "onBackup()"); ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); // we'll reuse these DataOutputStream outWriter = new DataOutputStream(bufStream); ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream(); // we'll reuse these DataOutputStream outputBufferStream = new DataOutputStream(outputBuffer); parseStateFile(oldState); // If the stored version string differs, we need to re-backup all Loading @@ -148,11 +148,9 @@ public class PackageManagerBackupAgent extends BackupAgent { */ if (!mExisting.contains(GLOBAL_METADATA_KEY)) { if (DEBUG) Slog.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); outputBufferStream.writeInt(Build.VERSION.SDK_INT); outputBufferStream.writeUTF(Build.VERSION.INCREMENTAL); writeEntity(data, GLOBAL_METADATA_KEY, outputBuffer.toByteArray()); } else { if (DEBUG) Slog.v(TAG, "Global metadata key already stored"); // don't consider it to have been skipped/deleted Loading @@ -178,23 +176,25 @@ public class PackageManagerBackupAgent extends BackupAgent { 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 if (mExisting.contains(packName)) { // We have backed up this app 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 (info.versionCode == mStateVersions.get(packName).versionCode) { continue; } } if (info.signatures == null || info.signatures.length == 0) { Slog.w(TAG, "Not backing up package " + packName + " since it appears to have no signatures."); continue; } if (doBackup) { // We need to store this app's metadata /* * Metadata for each package: Loading @@ -204,23 +204,18 @@ public class PackageManagerBackupAgent extends BackupAgent { */ // marshal the version code in a canonical form bufStream.reset(); outWriter.writeInt(info.versionCode); byte[] versionBuf = bufStream.toByteArray(); byte[] sigs = flattenSignatureArray(info.signatures); outputBuffer.reset(); outputBufferStream.writeInt(info.versionCode); writeSignatureArray(outputBufferStream, info.signatures); if (DEBUG) { Slog.v(TAG, "+ metadata for " + packName Slog.v(TAG, "+ writing metadata for " + packName + " version=" + info.versionCode + " versionLen=" + versionBuf.length + " sigsLen=" + sigs.length); + " entityLen=" + outputBuffer.size()); } // 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); } writeEntity(data, packName, outputBuffer.toByteArray()); } } Loading @@ -246,6 +241,12 @@ public class PackageManagerBackupAgent extends BackupAgent { writeStateFile(mAllPackages, newState); } private static void writeEntity(BackupDataOutput data, String key, byte[] bytes) throws IOException { data.writeEntityHeader(key, bytes.length); data.writeEntityData(bytes, bytes.length); } // "Restore" here is a misnomer. What we're really doing is reading back the // set of app signatures associated with each backed-up app in this restore // image. We'll use those later to determine what we can legitimately restore. Loading @@ -263,13 +264,13 @@ public class PackageManagerBackupAgent extends BackupAgent { if (DEBUG) Slog.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); byte[] inputBytes = new byte[dataSize]; data.readEntityData(inputBytes, 0, dataSize); ByteArrayInputStream inputBuffer = new ByteArrayInputStream(inputBytes); DataInputStream inputBufferStream = new DataInputStream(inputBuffer); if (key.equals(GLOBAL_METADATA_KEY)) { int storedSdkVersion = in.readInt(); int storedSdkVersion = inputBufferStream.readInt(); if (DEBUG) Slog.v(TAG, " storedSystemVersion = " + storedSystemVersion); if (storedSystemVersion > Build.VERSION.SDK_INT) { // returning before setting the sig map means we rejected the restore set Loading @@ -277,7 +278,7 @@ public class PackageManagerBackupAgent extends BackupAgent { return; } mStoredSdkVersion = storedSdkVersion; mStoredIncrementalVersion = in.readUTF(); mStoredIncrementalVersion = inputBufferStream.readUTF(); mHasMetadata = true; if (DEBUG) { Slog.i(TAG, "Restore set version " + storedSystemVersion Loading @@ -287,14 +288,20 @@ public class PackageManagerBackupAgent extends BackupAgent { } } else { // it's a file metadata record int versionCode = in.readInt(); Signature[] sigs = unflattenSignatureArray(in); int versionCode = inputBufferStream.readInt(); Signature[] sigs = readSignatureArray(inputBufferStream); if (DEBUG) { Slog.i(TAG, " restored metadata for " + key Slog.i(TAG, " read metadata for " + key + " dataSize=" + dataSize + " versionCode=" + versionCode + " sigs=" + sigs); } if (sigs == null || sigs.length == 0) { Slog.w(TAG, "Not restoring package " + key + " since it appears to have no signatures."); continue; } ApplicationInfo app = new ApplicationInfo(); app.packageName = key; restoredApps.add(app); Loading @@ -306,37 +313,30 @@ public class PackageManagerBackupAgent extends BackupAgent { mRestoredSignatures = sigMap; } private static void writeSignatureArray(DataOutputStream out, Signature[] sigs) throws IOException { // write the number of signatures in the array out.writeInt(sigs.length); // Util: convert an array of Signatures into a flattened byte buffer. The // flattened format contains enough info to reconstruct the signature array. private byte[] flattenSignatureArray(Signature[] allSigs) { ByteArrayOutputStream outBuf = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(outBuf); // build the set of subsidiary buffers try { // first the # of signatures in the array out.writeInt(allSigs.length); // then the signatures themselves, length + flattened buffer for (Signature sig : allSigs) { // write the signatures themselves, length + flattened buffer for (Signature sig : sigs) { byte[] flat = sig.toByteArray(); out.writeInt(flat.length); out.write(flat); } } catch (IOException e) { // very strange; we're writing to memory here. abort. return null; } return outBuf.toByteArray(); private static Signature[] readSignatureArray(DataInputStream in) { try { int num; try { num = in.readInt(); } catch (EOFException e) { // clean termination Slog.w(TAG, "Read empty signature block"); return null; } private Signature[] unflattenSignatureArray(/*byte[] buffer*/ DataInputStream in) { Signature[] sigs = null; try { int num = in.readInt(); if (DEBUG) Slog.v(TAG, " ... unflatten read " + num); // Sensical? Loading @@ -345,24 +345,18 @@ public class PackageManagerBackupAgent extends BackupAgent { throw new IllegalStateException("Bad restore state"); } sigs = new Signature[num]; Signature[] sigs = new Signature[num]; for (int i = 0; i < num; i++) { int len = in.readInt(); byte[] flatSig = new byte[len]; in.read(flatSig); sigs[i] = new Signature(flatSig); } } catch (EOFException e) { // clean termination if (sigs == null) { Slog.w(TAG, "Empty signature block found"); } return sigs; } catch (IOException e) { Slog.e(TAG, "Unable to unflatten sigs"); Slog.e(TAG, "Unable to read signatures"); return null; } return sigs; } // Util: parse out an existing state file into a usable structure Loading Loading
services/java/com/android/server/PackageManagerBackupAgent.java +83 −89 Original line number Diff line number Diff line Loading @@ -122,8 +122,8 @@ public class PackageManagerBackupAgent extends BackupAgent { ParcelFileDescriptor newState) { if (DEBUG) Slog.v(TAG, "onBackup()"); ByteArrayOutputStream bufStream = new ByteArrayOutputStream(); // we'll reuse these DataOutputStream outWriter = new DataOutputStream(bufStream); ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream(); // we'll reuse these DataOutputStream outputBufferStream = new DataOutputStream(outputBuffer); parseStateFile(oldState); // If the stored version string differs, we need to re-backup all Loading @@ -148,11 +148,9 @@ public class PackageManagerBackupAgent extends BackupAgent { */ if (!mExisting.contains(GLOBAL_METADATA_KEY)) { if (DEBUG) Slog.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); outputBufferStream.writeInt(Build.VERSION.SDK_INT); outputBufferStream.writeUTF(Build.VERSION.INCREMENTAL); writeEntity(data, GLOBAL_METADATA_KEY, outputBuffer.toByteArray()); } else { if (DEBUG) Slog.v(TAG, "Global metadata key already stored"); // don't consider it to have been skipped/deleted Loading @@ -178,23 +176,25 @@ public class PackageManagerBackupAgent extends BackupAgent { 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 if (mExisting.contains(packName)) { // We have backed up this app 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 (info.versionCode == mStateVersions.get(packName).versionCode) { continue; } } if (info.signatures == null || info.signatures.length == 0) { Slog.w(TAG, "Not backing up package " + packName + " since it appears to have no signatures."); continue; } if (doBackup) { // We need to store this app's metadata /* * Metadata for each package: Loading @@ -204,23 +204,18 @@ public class PackageManagerBackupAgent extends BackupAgent { */ // marshal the version code in a canonical form bufStream.reset(); outWriter.writeInt(info.versionCode); byte[] versionBuf = bufStream.toByteArray(); byte[] sigs = flattenSignatureArray(info.signatures); outputBuffer.reset(); outputBufferStream.writeInt(info.versionCode); writeSignatureArray(outputBufferStream, info.signatures); if (DEBUG) { Slog.v(TAG, "+ metadata for " + packName Slog.v(TAG, "+ writing metadata for " + packName + " version=" + info.versionCode + " versionLen=" + versionBuf.length + " sigsLen=" + sigs.length); + " entityLen=" + outputBuffer.size()); } // 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); } writeEntity(data, packName, outputBuffer.toByteArray()); } } Loading @@ -246,6 +241,12 @@ public class PackageManagerBackupAgent extends BackupAgent { writeStateFile(mAllPackages, newState); } private static void writeEntity(BackupDataOutput data, String key, byte[] bytes) throws IOException { data.writeEntityHeader(key, bytes.length); data.writeEntityData(bytes, bytes.length); } // "Restore" here is a misnomer. What we're really doing is reading back the // set of app signatures associated with each backed-up app in this restore // image. We'll use those later to determine what we can legitimately restore. Loading @@ -263,13 +264,13 @@ public class PackageManagerBackupAgent extends BackupAgent { if (DEBUG) Slog.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); byte[] inputBytes = new byte[dataSize]; data.readEntityData(inputBytes, 0, dataSize); ByteArrayInputStream inputBuffer = new ByteArrayInputStream(inputBytes); DataInputStream inputBufferStream = new DataInputStream(inputBuffer); if (key.equals(GLOBAL_METADATA_KEY)) { int storedSdkVersion = in.readInt(); int storedSdkVersion = inputBufferStream.readInt(); if (DEBUG) Slog.v(TAG, " storedSystemVersion = " + storedSystemVersion); if (storedSystemVersion > Build.VERSION.SDK_INT) { // returning before setting the sig map means we rejected the restore set Loading @@ -277,7 +278,7 @@ public class PackageManagerBackupAgent extends BackupAgent { return; } mStoredSdkVersion = storedSdkVersion; mStoredIncrementalVersion = in.readUTF(); mStoredIncrementalVersion = inputBufferStream.readUTF(); mHasMetadata = true; if (DEBUG) { Slog.i(TAG, "Restore set version " + storedSystemVersion Loading @@ -287,14 +288,20 @@ public class PackageManagerBackupAgent extends BackupAgent { } } else { // it's a file metadata record int versionCode = in.readInt(); Signature[] sigs = unflattenSignatureArray(in); int versionCode = inputBufferStream.readInt(); Signature[] sigs = readSignatureArray(inputBufferStream); if (DEBUG) { Slog.i(TAG, " restored metadata for " + key Slog.i(TAG, " read metadata for " + key + " dataSize=" + dataSize + " versionCode=" + versionCode + " sigs=" + sigs); } if (sigs == null || sigs.length == 0) { Slog.w(TAG, "Not restoring package " + key + " since it appears to have no signatures."); continue; } ApplicationInfo app = new ApplicationInfo(); app.packageName = key; restoredApps.add(app); Loading @@ -306,37 +313,30 @@ public class PackageManagerBackupAgent extends BackupAgent { mRestoredSignatures = sigMap; } private static void writeSignatureArray(DataOutputStream out, Signature[] sigs) throws IOException { // write the number of signatures in the array out.writeInt(sigs.length); // Util: convert an array of Signatures into a flattened byte buffer. The // flattened format contains enough info to reconstruct the signature array. private byte[] flattenSignatureArray(Signature[] allSigs) { ByteArrayOutputStream outBuf = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(outBuf); // build the set of subsidiary buffers try { // first the # of signatures in the array out.writeInt(allSigs.length); // then the signatures themselves, length + flattened buffer for (Signature sig : allSigs) { // write the signatures themselves, length + flattened buffer for (Signature sig : sigs) { byte[] flat = sig.toByteArray(); out.writeInt(flat.length); out.write(flat); } } catch (IOException e) { // very strange; we're writing to memory here. abort. return null; } return outBuf.toByteArray(); private static Signature[] readSignatureArray(DataInputStream in) { try { int num; try { num = in.readInt(); } catch (EOFException e) { // clean termination Slog.w(TAG, "Read empty signature block"); return null; } private Signature[] unflattenSignatureArray(/*byte[] buffer*/ DataInputStream in) { Signature[] sigs = null; try { int num = in.readInt(); if (DEBUG) Slog.v(TAG, " ... unflatten read " + num); // Sensical? Loading @@ -345,24 +345,18 @@ public class PackageManagerBackupAgent extends BackupAgent { throw new IllegalStateException("Bad restore state"); } sigs = new Signature[num]; Signature[] sigs = new Signature[num]; for (int i = 0; i < num; i++) { int len = in.readInt(); byte[] flatSig = new byte[len]; in.read(flatSig); sigs[i] = new Signature(flatSig); } } catch (EOFException e) { // clean termination if (sigs == null) { Slog.w(TAG, "Empty signature block found"); } return sigs; } catch (IOException e) { Slog.e(TAG, "Unable to unflatten sigs"); Slog.e(TAG, "Unable to read signatures"); return null; } return sigs; } // Util: parse out an existing state file into a usable structure Loading