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

Commit 9ff53a71 authored by Christopher Tate's avatar Christopher Tate
Browse files

Implement full data backup through transport

Currently no timed/scheduled full-data backup operations are
performed by the OS, but the plumbing is now in place and can
be tested using 'adb shell bmgr fullbackup pkg [pkg2 pkg3 ...]'.

The LocalTransport test transport implementation has been augmented
to support the new full-data backup API as well.

In addition, 'adb backup' now takes the -compress/-nocompress
command line options to control whether the resulting archive is
compressed before leaving the device.  Previously the archive was
always compressed.  (The default is still to compress, as it will
usually reduce the archive size considerably.)

Internally, the core implementation of gathering the full backup
data stream from the target application has been refactored into
an "engine" component that is shared by both 'adb backup' and the
transport-oriented full backup task.  The archive file header
generation, encryption, and compression logic are now factored out
of the engine itself instead of being hardwired into the data
handling.

Bug 15329632

Change-Id: I4a044faa4070d684ef457bd3e11771198cdf557c
parent ad60891a
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.app.backup.IRestoreSession;
import android.os.RemoteException;
import android.os.ServiceManager;

import java.util.ArrayList;
import java.util.HashSet;

public final class Bmgr {
@@ -102,6 +103,11 @@ public final class Bmgr {
            return;
        }

        if ("fullbackup".equals(op)) {
            doFullTransportBackup();
            return;
        }

        System.err.println("Unknown command");
        showUsage();
    }
@@ -165,6 +171,21 @@ public final class Bmgr {
        }
    }

    private void doFullTransportBackup() {
        System.out.println("Performing full transport backup");

        String pkg;
        while ((pkg = nextArg()) != null) {
            System.out.println("    Package " + pkg + " ...");
            try {
                mBmgr.fullTransportBackup(new String[] { pkg });
            } catch (RemoteException e) {
                System.err.println(e.toString());
                System.err.println(BMGR_NOT_RUNNING_ERR);
            }
        }
    }

    private void doTransport() {
        try {
            String which = nextArg();
+6 −1
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ public final class Backup {
        boolean doEverything = false;
        boolean doWidgets = false;
        boolean allIncludesSystem = true;
        boolean doCompress = true;

        String arg;
        while ((arg = nextArg()) != null) {
@@ -95,6 +96,10 @@ public final class Backup {
                    doWidgets = false;
                } else if ("-all".equals(arg)) {
                    doEverything = true;
                } else if ("-compress".equals(arg)) {
                    doCompress = true;
                } else if ("-nocompress".equals(arg)) {
                    doCompress = false;
                } else {
                    Log.w(TAG, "Unknown backup flag " + arg);
                    continue;
@@ -119,7 +124,7 @@ public final class Backup {
            fd = ParcelFileDescriptor.adoptFd(socketFd);
            String[] packArray = new String[packages.size()];
            mBackupManager.fullBackup(fd, saveApks, saveObbs, saveShared, doWidgets,
                    doEverything, allIncludesSystem, packages.toArray(packArray));
                    doEverything, allIncludesSystem, doCompress, packages.toArray(packArray));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to invoke backup manager for backup");
        } finally {
+67 −0
Original line number Diff line number Diff line
@@ -328,6 +328,58 @@ public class BackupTransport {
        return BackupTransport.TRANSPORT_ERROR;
    }

    // ------------------------------------------------------------------------------------
    // Full restore interfaces

    /**
     * Ask the transport to set up to perform a full data restore of the given packages.
     *
     * @param token A backup token as returned by {@link #getAvailableRestoreSets}
     *    or {@link #getCurrentRestoreSet}.
     * @param targetPackage The names of the packages whose data is being requested.
     * @return TRANSPORT_OK to indicate that the OS may proceed with requesting
     *    restore data; TRANSPORT_ERROR to indicate a fatal error condition that precludes
     *    performing any restore at this time.
     */
    public int prepareFullRestore(long token, String[] targetPackages) {
        return BackupTransport.TRANSPORT_OK;
    }

    /**
     * Ask the transport what package's full data will be restored next.  When all apps'
     * data has been delivered, the transport should return {@code null} here.
     * @return The package name of the next application whose data will be restored, or
     *    {@code null} if all available package has been delivered.
     */
    public String getNextFullRestorePackage() {
        return null;
    }

    /**
     * Ask the transport to provide data for the "current" package being restored.  The
     * transport then writes some data to the socket supplied to this call, and returns
     * the number of bytes written.  The system will then read that many bytes and
     * stream them to the application's agent for restore, then will call this method again
     * to receive the next chunk of the archive.  This sequence will be repeated until the
     * transport returns zero indicating that all of the package's data has been delivered
     * (or returns a negative value indicating some sort of hard error condition at the
     * transport level).
     *
     * <p>After this method returns zero, the system will then call
     * {@link #getNextFullRestorePackage()} to begin the restore process for the next
     * application, and the sequence begins again.
     *
     * @param socket The file descriptor that the transport will use for delivering the
     *    streamed archive.
     * @return 0 when no more data for the current package is available.  A positive value
     *    indicates the presence of that much data to be delivered to the app.  A negative
     *    return value is treated as equivalent to {@link BackupTransport#TRANSPORT_ERROR},
     *    indicating a fatal error condition that precludes further restore operations
     *    on the current dataset.
     */
    public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) {
        return 0;
    }
    /**
     * Bridge between the actual IBackupTransport implementation and the stable API.  If the
     * binder interface needs to change, we use this layer to translate so that we can
@@ -411,5 +463,20 @@ public class BackupTransport {
        public void finishRestore() throws RemoteException {
            BackupTransport.this.finishRestore();
        }

        @Override
        public long requestFullBackupTime() throws RemoteException {
            return BackupTransport.this.requestFullBackupTime();
        }

        @Override
        public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) throws RemoteException {
            return BackupTransport.this.performFullBackup(targetPackage, socket);
        }

        @Override
        public int sendBackupData(int numBytes) throws RemoteException {
            return BackupTransport.this.sendBackupData(numBytes);
        }
    }
}
+9 −1
Original line number Diff line number Diff line
@@ -168,7 +168,15 @@ interface IBackupManager {
     */
    void fullBackup(in ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs,
            boolean includeShared, boolean doWidgets, boolean allApps, boolean allIncludesSystem,
            in String[] packageNames);
            boolean doCompress, in String[] packageNames);

    /**
     * Perform a full-dataset backup of the given applications via the currently active
     * transport.
     *
     * @param packageNames The package names of the apps whose data are to be backed up.
     */
    void fullTransportBackup(in String[] packageNames);

    /**
     * Restore device content from the data stream passed through the given socket.  The
+4 −0
Original line number Diff line number Diff line
@@ -187,4 +187,8 @@ interface IBackupTransport {
     * freeing any resources and connections used during the restore process.
     */
    void finishRestore();

    long requestFullBackupTime();
    int performFullBackup(in PackageInfo targetPackage, in ParcelFileDescriptor socket);
    int sendBackupData(int numBytes);
}
Loading