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

Commit 938e0f56 authored by Ruslan Tkhakokhov's avatar Ruslan Tkhakokhov Committed by Android (Google) Code Review
Browse files

Merge "[Multi-user] Add -user param to adb backup/restore"

parents 67fb3ca9 a2fe6c5b
Loading
Loading
Loading
Loading
+58 −14
Original line number Diff line number Diff line
@@ -16,13 +16,17 @@

package com.android.commands.bu;

import android.annotation.UserIdInt;
import android.app.backup.IBackupManager;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.system.OsConstants;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

import java.io.IOException;
import java.util.ArrayList;

@@ -33,35 +37,50 @@ public final class Backup {
    int mNextArg;
    IBackupManager mBackupManager;

    @VisibleForTesting
    Backup(IBackupManager backupManager) {
        mBackupManager = backupManager;
    }

    Backup() {
        mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService("backup"));
    }

    public static void main(String[] args) {
        Log.d(TAG, "Beginning: " + args[0]);
        mArgs = args;
        try {
            new Backup().run();
            new Backup().run(args);
        } catch (Exception e) {
            Log.e(TAG, "Error running backup/restore", e);
        }
        Log.d(TAG, "Finished.");
    }

    public void run() {
        mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService("backup"));
    public void run(String[] args) {
        if (mBackupManager == null) {
            Log.e(TAG, "Can't obtain Backup Manager binder");
            return;
        }

        Log.d(TAG, "Beginning: " + args[0]);
        mArgs = args;

        int userId = parseUserId();
        if (!isBackupActiveForUser(userId)) {
            Log.e(TAG, "BackupManager is not available for user " + userId);
            return;
        }

        String arg = nextArg();
        if (arg.equals("backup")) {
            doBackup(OsConstants.STDOUT_FILENO);
            doBackup(OsConstants.STDOUT_FILENO, userId);
        } else if (arg.equals("restore")) {
            doRestore(OsConstants.STDIN_FILENO);
            doRestore(OsConstants.STDIN_FILENO, userId);
        } else {
            showUsage();
        }
    }

    private void doBackup(int socketFd) {
    private void doBackup(int socketFd, @UserIdInt int userId) {
        ArrayList<String> packages = new ArrayList<String>();
        boolean saveApks = false;
        boolean saveObbs = false;
@@ -105,6 +124,10 @@ public final class Backup {
                    doKeyValue = true;
                } else if ("-nokeyvalue".equals(arg)) {
                    doKeyValue = false;
                } else if ("-user".equals(arg)) {
                    // User ID has been processed in run(), ignore the next argument.
                    nextArg();
                    continue;
                } else {
                    Log.w(TAG, "Unknown backup flag " + arg);
                    continue;
@@ -128,7 +151,7 @@ public final class Backup {
        try {
            fd = ParcelFileDescriptor.adoptFd(socketFd);
            String[] packArray = new String[packages.size()];
            mBackupManager.adbBackup(fd, saveApks, saveObbs, saveShared, doWidgets, doEverything,
            mBackupManager.adbBackup(userId, fd, saveApks, saveObbs, saveShared, doWidgets, doEverything,
                    allIncludesSystem, doCompress, doKeyValue, packages.toArray(packArray));
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to invoke backup manager for backup");
@@ -143,12 +166,12 @@ public final class Backup {
        }
    }

    private void doRestore(int socketFd) {
    private void doRestore(int socketFd, @UserIdInt int userId) {
        // No arguments to restore
        ParcelFileDescriptor fd = null;
        try {
            fd = ParcelFileDescriptor.adoptFd(socketFd);
            mBackupManager.adbRestore(fd);
            mBackupManager.adbRestore(userId, fd);
        } catch (RemoteException e) {
            Log.e(TAG, "Unable to invoke backup manager for restore");
        } finally {
@@ -160,11 +183,31 @@ public final class Backup {
        }
    }

    private @UserIdInt int parseUserId() {
        for (int argNumber = 0; argNumber < mArgs.length - 1; argNumber++) {
            if ("-user".equals(mArgs[argNumber])) {
                return UserHandle.parseUserArg(mArgs[argNumber + 1]);
            }
        }

        return UserHandle.USER_SYSTEM;
    }

    private boolean isBackupActiveForUser(int userId) {
        try {
            return mBackupManager.isBackupServiceActive(userId);
        } catch (RemoteException e) {
            Log.e(TAG, "Could not access BackupManager: " + e.toString());
            return false;
        }
    }

    private static void showUsage() {
        System.err.println(" backup [-f FILE] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all]");
        System.err.println("        [-system|-nosystem] [-keyvalue|-nokeyvalue] [PACKAGE...]");
        System.err.println(" backup [-user USER_ID] [-f FILE] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared]");
        System.err.println("        [-all] [-system|-nosystem] [-keyvalue|-nokeyvalue] [PACKAGE...]");
        System.err.println("     write an archive of the device's data to FILE [default=backup.adb]");
        System.err.println("     package list optional if -all/-shared are supplied");
        System.err.println("     -user: user ID for which to perform the operation (default - system user)");
        System.err.println("     -apk/-noapk: do/don't back up .apk files (default -noapk)");
        System.err.println("     -obb/-noobb: do/don't back up .obb files (default -noobb)");
        System.err.println("     -shared|-noshared: do/don't back up shared storage (default -noshared)");
@@ -172,7 +215,8 @@ public final class Backup {
        System.err.println("     -system|-nosystem: include system apps in -all (default -system)");
        System.err.println("     -keyvalue|-nokeyvalue: include apps that perform key/value backups.");
        System.err.println("         (default -nokeyvalue)");
        System.err.println(" restore FILE             restore device contents from FILE");
        System.err.println(" restore [-user USER_ID] FILE       restore device contents from FILE");
        System.err.println("     -user: user ID for which to perform the operation (default - system user)");
    }

    private String nextArg() {
+10 −3
Original line number Diff line number Diff line
@@ -189,8 +189,11 @@ interface IBackupManager {
     * completed.
     *
     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
     * If the {@code userId} is different from the calling user id, then the caller must hold the
     * android.permission.INTERACT_ACROSS_USERS_FULL permission.
     *
     * @param fd The file descriptor to which a 'tar' file stream is to be written
     * @param userId User id for which backup should be performed.
     * @param fd The file descriptor to which a 'tar' file stream is to be written.
     * @param includeApks If <code>true</code>, the resulting tar stream will include the
     *     application .apk files themselves as well as their data.
     * @param includeObbs If <code>true</code>, the resulting tar stream will include any
@@ -209,7 +212,7 @@ interface IBackupManager {
     * @param packageNames The package names of the apps whose data (and optionally .apk files)
     *     are to be backed up.  The <code>allApps</code> parameter supersedes this.
     */
    void adbBackup(in ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs,
    void adbBackup(int userId, in ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs,
            boolean includeShared, boolean doWidgets, boolean allApps, boolean allIncludesSystem,
            boolean doCompress, boolean doKeyValue, in String[] packageNames);

@@ -227,8 +230,12 @@ interface IBackupManager {
     * Currently only used by the 'adb restore' command.
     *
     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
     * If the {@code userId} is different from the calling user id, then the caller must hold the
     * android.permission.INTERACT_ACROSS_USERS_FULL.
     *
     * @param userId User id for which restore should be performed.
     */
    void adbRestore(in ParcelFileDescriptor fd);
    void adbRestore(int userId, in ParcelFileDescriptor fd);

    /**
     * Confirm that the requested full backup/restore operation can proceed.  The system will
+6 −1
Original line number Diff line number Diff line
@@ -477,6 +477,7 @@ public class BackupManagerService {
     * requires on-screen confirmation by the user.
     */
    public void adbBackup(
            @UserIdInt int userId,
            ParcelFileDescriptor fd,
            boolean includeApks,
            boolean includeObbs,
@@ -487,6 +488,8 @@ public class BackupManagerService {
            boolean doCompress,
            boolean doKeyValue,
            String[] packageNames) {
        enforceCallingPermissionOnUserId(userId, "adbBackup");

        mUserBackupManagerService.adbBackup(
                fd,
                includeApks,
@@ -505,7 +508,9 @@ public class BackupManagerService {
     * is synchronous and does not return to the caller until the restore has been completed. It
     * requires on-screen confirmation by the user.
     */
    public void adbRestore(ParcelFileDescriptor fd) {
    public void adbRestore(@UserIdInt int userId, ParcelFileDescriptor fd) {
        enforceCallingPermissionOnUserId(userId, "setBackupEnabled");

        mUserBackupManagerService.adbRestore(fd);
    }

+7 −8
Original line number Diff line number Diff line
@@ -389,14 +389,13 @@ public class Trampoline extends IBackupManager.Stub {
        backupNowForUser(binderGetCallingUserId());
    }

    @Override
    public void adbBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs,
            boolean includeShared, boolean doWidgets, boolean allApps,
            boolean allIncludesSystem, boolean doCompress, boolean doKeyValue, String[] packageNames)
                    throws RemoteException {
    public void adbBackup(@UserIdInt int userId, ParcelFileDescriptor fd,
            boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets,
            boolean allApps, boolean allIncludesSystem, boolean doCompress, boolean doKeyValue,
            String[] packageNames) throws RemoteException {
        BackupManagerService svc = mService;
        if (svc != null) {
            svc.adbBackup(fd, includeApks, includeObbs, includeShared, doWidgets,
            svc.adbBackup(userId, fd, includeApks, includeObbs, includeShared, doWidgets,
                    allApps, allIncludesSystem, doCompress, doKeyValue, packageNames);
        }
    }
@@ -410,10 +409,10 @@ public class Trampoline extends IBackupManager.Stub {
    }

    @Override
    public void adbRestore(ParcelFileDescriptor fd) throws RemoteException {
    public void adbRestore(@UserIdInt int userId, ParcelFileDescriptor fd) throws RemoteException {
        BackupManagerService svc = mService;
        if (svc != null) {
            svc.adbRestore(fd);
            svc.adbRestore(userId, fd);
        }
    }

+4 −3
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE;
import static com.android.server.backup.internal.BackupHandler.MSG_SCHEDULE_BACKUP_PACKAGE;

import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.AppGlobals;
@@ -2423,9 +2424,9 @@ public class UserBackupManagerService {
     * return to the caller until the backup has been completed. It requires on-screen confirmation
     * by the user.
     */
    public void adbBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs,
            boolean includeShared, boolean doWidgets, boolean doAllApps, boolean includeSystem,
            boolean compress, boolean doKeyValue, String[] pkgList) {
    public void adbBackup(ParcelFileDescriptor fd, boolean includeApks,
            boolean includeObbs, boolean includeShared, boolean doWidgets, boolean doAllApps,
            boolean includeSystem, boolean compress, boolean doKeyValue, String[] pkgList) {
        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "adbBackup");

        final int callingUserHandle = UserHandle.getCallingUserId();
Loading