Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b92c45a4 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 4831 into donut

* changes:
  Add app version to the backup metadata
parents 1585bd24 6aa41f4c
Loading
Loading
Loading
Loading
+28 −21
Original line number Diff line number Diff line
@@ -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;
@@ -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
@@ -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) {
@@ -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) {
@@ -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;
            }

@@ -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;
@@ -800,6 +801,7 @@ class BackupManagerService extends IBackupManager.Stub {

        @Override
        public void run() {
            if (DEBUG) Log.v(TAG, "Beginning restore process");
            /**
             * Restore sequence:
             *
@@ -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);
                                }
                            }
                        }
@@ -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);
            }
        }
    }
+47 −22
Original line number Diff line number Diff line
@@ -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
@@ -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.
@@ -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;
        }
@@ -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)) {
@@ -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.
@@ -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!");
                }
@@ -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) {
@@ -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;
@@ -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 {