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

Commit 25a747f5 authored by Christopher Tate's avatar Christopher Tate
Browse files

Add an 'init everything' operation to the first backup pass

IBackupTransport.performBackup() now takes a flag "wipeAllFirst", which if set
will result in the entire restore set for the current device/account being wiped
clean prior to the storage of the provided package.  This ensures that a device
on which backup has just been enabled will not confront potentially-stale
information, nor will the restore set potentially contain mismatched data from
orphaned packages.

The Backup Manager has also been revised to pass this flag when first backing up
its master metadata block (and never pass it thereafter unless something has
caused the backup state tracking to be erased, e.g. the user has opted out of
backup and then later re-enabled it).
parent d163f4ba
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -77,10 +77,15 @@ interface IBackupTransport {
     * @param data The data stream that resulted from invoking the application's
     *   BackupService.doBackup() method.  This may be a pipe rather than a file on
     *   persistent media, so it may not be seekable.
     * @param wipeAllFirst When true, <i>all</i> backed-up data for the current device/account
     *   will be erased prior to the storage of the data provided here.  The purpose of this
     *   is to provide a guarantee that no stale data exists in the restore set when the
     *   device begins providing backups.
     * @return false if errors occurred (the backup should be aborted and rescheduled),
     *   true if everything is OK so far (but {@link #finishBackup} must be called).
     */
    boolean performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd);
    boolean performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd,
            boolean wipeAllFirst);

    /**
     * Erase the give application's data from the backup destination.  This clears
+21 −2
Original line number Diff line number Diff line
@@ -56,12 +56,16 @@ public class LocalTransport extends IBackupTransport.Stub {
        return 0;
    }

    public boolean performBackup(PackageInfo packageInfo, ParcelFileDescriptor data)
            throws RemoteException {
    public boolean performBackup(PackageInfo packageInfo, ParcelFileDescriptor data,
            boolean wipeAllFirst) throws RemoteException {
        if (DEBUG) Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName);

        File packageDir = new File(mDataDir, packageInfo.packageName);
        packageDir.mkdirs();
        if (wipeAllFirst) {
            if (DEBUG) Log.v(TAG, "wiping all data first");
            deleteContents(mDataDir);
        }

        // Each 'record' in the restore set is kept in its own file, named by
        // the record key.  Wind through the data file, extracting individual
@@ -111,6 +115,21 @@ public class LocalTransport extends IBackupTransport.Stub {
        }
    }

    // Deletes the contents but not the given directory
    private void deleteContents(File dirname) {
        File[] contents = dirname.listFiles();
        if (contents != null) {
            for (File f : contents) {
                if (f.isDirectory()) {
                    // delete the directory's contents then fall through
                    // and delete the directory itself.
                    deleteContents(f);
                }
                f.delete();
            }
        }
    }

    public boolean clearBackupData(PackageInfo packageInfo) {
        if (DEBUG) Log.v(TAG, "clearBackupData() pkg=" + packageInfo.packageName);

+16 −3
Original line number Diff line number Diff line
@@ -949,11 +949,11 @@ class BackupManagerService extends IBackupManager.Stub {
            }
        }

        void processOneBackup(BackupRequest request, IBackupAgent agent, IBackupTransport transport) {
        void processOneBackup(BackupRequest request, IBackupAgent agent,
                IBackupTransport transport) {
            final String packageName = request.appInfo.packageName;
            if (DEBUG) Log.d(TAG, "processOneBackup doBackup() on " + packageName);

            // !!! TODO: get the state file dir from the transport
            File savedStateName = new File(mStateDir, packageName);
            File backupDataName = new File(mDataDir, packageName + ".data");
            File newStateName = new File(mStateDir, packageName + ".new");
@@ -962,6 +962,12 @@ class BackupManagerService extends IBackupManager.Stub {
            ParcelFileDescriptor backupData = null;
            ParcelFileDescriptor newState = null;

            // Usually we won't force a server-side init, except the first time
            // we ever back up following enable of backup.  To keep the bookkeeping
            // simple, we detect this here rather than maintain state throughout
            // the backup manager.
            boolean doInit = false;

            PackageInfo packInfo;
            try {
                // Look up the package info & signatures.  This is first so that if it
@@ -971,6 +977,13 @@ class BackupManagerService extends IBackupManager.Stub {
                    // The metadata 'package' is synthetic
                    packInfo = new PackageInfo();
                    packInfo.packageName = packageName;

                    // if there's no metadata backup state, this must be the
                    // first time we've done one since enabling it.
                    if (savedStateName.exists() == false) {
                        if (DEBUG) Log.i(TAG, "First backup pass, issuing init");
                        doInit = true;
                    }
                } else {
                    packInfo = mPackageManager.getPackageInfo(packageName,
                        PackageManager.GET_SIGNATURES);
@@ -1023,7 +1036,7 @@ class BackupManagerService extends IBackupManager.Stub {
                    // hold off on finishBackup() until the end, which implies holding off on
                    // renaming *all* the output state files (see below) until that happens.

                    if (!transport.performBackup(packInfo, backupData) ||
                    if (!transport.performBackup(packInfo, backupData, doInit) ||
                        !transport.finishBackup()) {
                        throw new Exception("Backup transport failed");
                    }