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

Commit f410de02 authored by Bernardo Rufino's avatar Bernardo Rufino
Browse files

Move adb backup/restore operations to Trampoline

From BMS.

Test: atest BackupManagerServiceTest TrampolineRoboTest TrampolineTest
Bug: 135661048
Change-Id: I7f839a37780c5164878fd9640486c209f99620cc
parent a83c2e08
Loading
Loading
Loading
Loading
+0 −95
Original line number Diff line number Diff line
@@ -20,10 +20,8 @@ import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.backup.IFullBackupRestoreObserver;
import android.content.Context;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.util.SparseArray;

@@ -90,99 +88,6 @@ public class BackupManagerService {
     */
    // TODO (b/118520567): Stop hardcoding system user when we pass in user id as a parameter

    // ---------------------------------------------
    // ADB BACKUP/RESTORE OPERATIONS
    // ---------------------------------------------

    /** Sets the backup password used when running adb backup. */
    public boolean setBackupPassword(String currentPassword, String newPassword) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(
                        UserHandle.USER_SYSTEM, "setBackupPassword()");

        return userBackupManagerService != null
                && userBackupManagerService.setBackupPassword(currentPassword, newPassword);
    }

    /** Returns {@code true} if adb backup was run with a password, else returns {@code false}. */
    public boolean hasBackupPassword() {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(
                        UserHandle.USER_SYSTEM, "hasBackupPassword()");

        return userBackupManagerService != null && userBackupManagerService.hasBackupPassword();
    }

    /**
     * Used by 'adb backup' to run a backup pass for packages {@code packageNames} supplied via the
     * command line, writing the resulting data stream to the supplied {@code fd}. This method is
     * synchronous and does not return to the caller until the backup has been completed. It
     * requires on-screen confirmation by the user.
     */
    public void adbBackup(
            @UserIdInt int userId,
            ParcelFileDescriptor fd,
            boolean includeApks,
            boolean includeObbs,
            boolean includeShared,
            boolean doWidgets,
            boolean doAllApps,
            boolean includeSystem,
            boolean doCompress,
            boolean doKeyValue,
            String[] packageNames) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "adbBackup()");

        if (userBackupManagerService != null) {
            userBackupManagerService.adbBackup(
                    fd,
                    includeApks,
                    includeObbs,
                    includeShared,
                    doWidgets,
                    doAllApps,
                    includeSystem,
                    doCompress,
                    doKeyValue,
                    packageNames);
        }
    }

    /**
     * Used by 'adb restore' to run a restore pass reading from the supplied {@code fd}. This method
     * 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(@UserIdInt int userId, ParcelFileDescriptor fd) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "adbRestore()");

        if (userBackupManagerService != null) {
            userBackupManagerService.adbRestore(fd);
        }
    }

    /**
     * Confirm that the previously requested adb backup/restore operation can proceed. This is used
     * to require a user-facing disclosure about the operation.
     */
    public void acknowledgeAdbBackupOrRestore(
            @UserIdInt int userId,
            int token,
            boolean allow,
            String currentPassword,
            String encryptionPassword,
            IFullBackupRestoreObserver observer) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "acknowledgeAdbBackupOrRestore()");

        if (userBackupManagerService != null) {
            userBackupManagerService.acknowledgeAdbBackupOrRestore(
                    token, allow, currentPassword, encryptionPassword, observer);
        }
    }

    // ---------------------------------------------
    //  SERVICE OPERATIONS
    // ---------------------------------------------
+92 −14
Original line number Diff line number Diff line
@@ -722,16 +722,33 @@ public class Trampoline extends IBackupManager.Stub {
        return userBackupManagerService != null && userBackupManagerService.isBackupEnabled();
    }

    /** Sets the backup password used when running adb backup. */
    @Override
    public boolean setBackupPassword(String currentPw, String newPw) throws RemoteException {
    public boolean setBackupPassword(String currentPassword, String newPassword) {
        int userId = binderGetCallingUserId();
        return (isUserReadyForBackup(userId)) && mService.setBackupPassword(currentPw, newPw);
        if (!isUserReadyForBackup(userId)) {
            return false;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(
                        UserHandle.USER_SYSTEM, "setBackupPassword()");

        return userBackupManagerService != null
                && userBackupManagerService.setBackupPassword(currentPassword, newPassword);
    }

    /** Returns {@code true} if adb backup was run with a password, else returns {@code false}. */
    @Override
    public boolean hasBackupPassword() throws RemoteException {
        int userId = binderGetCallingUserId();
        return (isUserReadyForBackup(userId)) && mService.hasBackupPassword();
        if (!isUserReadyForBackup(userId)) {
            return false;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(
                        UserHandle.USER_SYSTEM, "hasBackupPassword()");

        return userBackupManagerService != null && userBackupManagerService.hasBackupPassword();
    }

    @Override
@@ -759,13 +776,43 @@ public class Trampoline extends IBackupManager.Stub {
        }
    }

    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 {
        if (isUserReadyForBackup(userId)) {
            mService.adbBackup(userId, fd, includeApks, includeObbs, includeShared, doWidgets,
                    allApps, allIncludesSystem, doCompress, doKeyValue, packageNames);
    /**
     * Used by 'adb backup' to run a backup pass for packages {@code packageNames} supplied via the
     * command line, writing the resulting data stream to the supplied {@code fd}. This method is
     * synchronous and does not return to the caller until the backup has been completed. It
     * requires on-screen confirmation by the user.
     */
    @Override
    public void adbBackup(
            @UserIdInt int userId,
            ParcelFileDescriptor fd,
            boolean includeApks,
            boolean includeObbs,
            boolean includeShared,
            boolean doWidgets,
            boolean doAllApps,
            boolean includeSystem,
            boolean doCompress,
            boolean doKeyValue,
            String[] packageNames) {
        if (!isUserReadyForBackup(userId)) {
            return;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "adbBackup()");

        if (userBackupManagerService != null) {
            userBackupManagerService.adbBackup(
                    fd,
                    includeApks,
                    includeObbs,
                    includeShared,
                    doWidgets,
                    doAllApps,
                    includeSystem,
                    doCompress,
                    doKeyValue,
                    packageNames);
        }
    }

@@ -789,10 +836,21 @@ public class Trampoline extends IBackupManager.Stub {
        }
    }

    /**
     * Used by 'adb restore' to run a restore pass reading from the supplied {@code fd}. This method
     * is synchronous and does not return to the caller until the restore has been completed. It
     * requires on-screen confirmation by the user.
     */
    @Override
    public void adbRestore(@UserIdInt int userId, ParcelFileDescriptor fd) throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            mService.adbRestore(userId, fd);
    public void adbRestore(@UserIdInt int userId, ParcelFileDescriptor fd) {
        if (!isUserReadyForBackup(userId)) {
            return;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "adbRestore()");

        if (userBackupManagerService != null) {
            userBackupManagerService.adbRestore(fd);
        }
    }

@@ -806,11 +864,31 @@ public class Trampoline extends IBackupManager.Stub {
            IFullBackupRestoreObserver observer)
            throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            mService.acknowledgeAdbBackupOrRestore(userId, token, allow,
            acknowledgeAdbBackupOrRestore(userId, token, allow,
                    curPassword, encryptionPassword, observer);
        }
    }

    /**
     * Confirm that the previously requested adb backup/restore operation can proceed. This is used
     * to require a user-facing disclosure about the operation.
     */
    public void acknowledgeAdbBackupOrRestore(
            @UserIdInt int userId,
            int token,
            boolean allow,
            String currentPassword,
            String encryptionPassword,
            IFullBackupRestoreObserver observer) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "acknowledgeAdbBackupOrRestore()");

        if (userBackupManagerService != null) {
            userBackupManagerService.acknowledgeAdbBackupOrRestore(
                    token, allow, currentPassword, encryptionPassword, observer);
        }
    }

    @Override
    public void acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword,
            String encryptionPassword, IFullBackupRestoreObserver observer)
+0 −293
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import static org.testng.Assert.expectThrows;

import android.annotation.UserIdInt;
import android.app.Application;
import android.app.backup.IFullBackupRestoreObserver;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.os.Process;
@@ -213,298 +212,6 @@ public class BackupManagerServiceTest {
                backupManagerService.getServiceForUserIfCallerHasPermission(mUserOneId, "test"));
    }

    // ---------------------------------------------
    // Adb backup/restore tests
    // ---------------------------------------------

    /** Test that the backup service routes methods correctly to the user that requests it. */
    @Test
    public void testSetBackupPassword_onRegisteredUser_callsMethodForUser() throws Exception {
        registerUser(UserHandle.USER_SYSTEM, mUserOneService);
        BackupManagerService backupManagerService = createService();

        backupManagerService.setBackupPassword("currentPassword", "newPassword");

        verify(mUserOneService).setBackupPassword("currentPassword", "newPassword");
    }

    /** Test that the backup service does not route methods for non-registered users. */
    @Test
    public void testSetBackupPassword_onUnknownUser_doesNotPropagateCall() throws Exception {
        BackupManagerService backupManagerService = createService();

        backupManagerService.setBackupPassword("currentPassword", "newPassword");

        verify(mUserOneService, never()).setBackupPassword("currentPassword", "newPassword");
    }

    /** Test that the backup service routes methods correctly to the user that requests it. */
    @Test
    public void testHasBackupPassword_onRegisteredUser_callsMethodForUser() throws Exception {
        registerUser(UserHandle.USER_SYSTEM, mUserOneService);
        BackupManagerService backupManagerService = createService();

        backupManagerService.hasBackupPassword();

        verify(mUserOneService).hasBackupPassword();
    }

    /** Test that the backup service does not route methods for non-registered users. */
    @Test
    public void testHasBackupPassword_onUnknownUser_doesNotPropagateCall() throws Exception {
        BackupManagerService backupManagerService = createService();

        backupManagerService.hasBackupPassword();

        verify(mUserOneService, never()).hasBackupPassword();
    }

    /**
     * Test that the backup services throws a {@link SecurityException} if the caller does not have
     * INTERACT_ACROSS_USERS_FULL permission and passes a different user id.
     */
    @Test
    public void testAdbBackup_withoutPermission_throwsSecurityExceptionForNonCallingUser() {
        registerUser(mUserOneId, mUserOneService);
        BackupManagerService backupManagerService = createService();
        setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);

        expectThrows(
                SecurityException.class,
                () ->
                        backupManagerService.adbBackup(
                                mUserTwoId,
                                /* parcelFileDescriptor*/ null,
                                /* includeApks */ true,
                                /* includeObbs */ true,
                                /* includeShared */ true,
                                /* doWidgets */ true,
                                /* doAllApps */ true,
                                /* includeSystem */ true,
                                /* doCompress */ true,
                                /* doKeyValue */ true,
                                null));
    }

    /**
     * Test that the backup service does not throw a {@link SecurityException} if the caller has
     * INTERACT_ACROSS_USERS_FULL permission and passes a different user id.
     */
    @Test
    public void testAdbBackup_withPermission_propagatesForNonCallingUser() throws Exception {
        registerUser(mUserOneId, mUserOneService);
        registerUser(mUserTwoId, mUserTwoService);
        BackupManagerService backupManagerService = createService();

        ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest();
        setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true);

        backupManagerService.adbBackup(
                mUserTwoId,
                parcelFileDescriptor,
                /* includeApks */ true,
                /* includeObbs */ true,
                /* includeShared */ true,
                /* doWidgets */ true,
                /* doAllApps */ true,
                /* includeSystem */ true,
                /* doCompress */ true,
                /* doKeyValue */ true,
                ADB_TEST_PACKAGES);

        verify(mUserTwoService)
                .adbBackup(
                        parcelFileDescriptor,
                        /* includeApks */ true,
                        /* includeObbs */ true,
                        /* includeShared */ true,
                        /* doWidgets */ true,
                        /* doAllApps */ true,
                        /* includeSystem */ true,
                        /* doCompress */ true,
                        /* doKeyValue */ true,
                        ADB_TEST_PACKAGES);
    }

    /** Test that the backup service routes methods correctly to the user that requests it. */
    @Test
    public void testAdbBackup_onRegisteredUser_callsMethodForUser() throws Exception {
        registerUser(mUserOneId, mUserOneService);
        BackupManagerService backupManagerService = createService();
        ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest();
        setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);

        backupManagerService.adbBackup(
                mUserOneId,
                parcelFileDescriptor,
                /* includeApks */ true,
                /* includeObbs */ true,
                /* includeShared */ true,
                /* doWidgets */ true,
                /* doAllApps */ true,
                /* includeSystem */ true,
                /* doCompress */ true,
                /* doKeyValue */ true,
                ADB_TEST_PACKAGES);

        verify(mUserOneService)
                .adbBackup(
                        parcelFileDescriptor,
                        /* includeApks */ true,
                        /* includeObbs */ true,
                        /* includeShared */ true,
                        /* doWidgets */ true,
                        /* doAllApps */ true,
                        /* includeSystem */ true,
                        /* doCompress */ true,
                        /* doKeyValue */ true,
                        ADB_TEST_PACKAGES);
    }

    /** Test that the backup service does not route methods for non-registered users. */
    @Test
    public void testAdbBackup_onUnknownUser_doesNotPropagateCall() throws Exception {
        registerUser(mUserOneId, mUserOneService);
        BackupManagerService backupManagerService = createService();
        ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest();
        setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);

        backupManagerService.adbBackup(
                mUserTwoId,
                parcelFileDescriptor,
                /* includeApks */ true,
                /* includeObbs */ true,
                /* includeShared */ true,
                /* doWidgets */ true,
                /* doAllApps */ true,
                /* includeSystem */ true,
                /* doCompress */ true,
                /* doKeyValue */ true,
                ADB_TEST_PACKAGES);

        verify(mUserOneService, never())
                .adbBackup(
                        parcelFileDescriptor,
                        /* includeApks */ true,
                        /* includeObbs */ true,
                        /* includeShared */ true,
                        /* doWidgets */ true,
                        /* doAllApps */ true,
                        /* includeSystem */ true,
                        /* doCompress */ true,
                        /* doKeyValue */ true,
                        ADB_TEST_PACKAGES);
    }

    /**
     * Test that the backup services throws a {@link SecurityException} if the caller does not have
     * INTERACT_ACROSS_USERS_FULL permission and passes a different user id.
     */
    @Test
    public void testAdbRestore_withoutPermission_throwsSecurityExceptionForNonCallingUser() {
        registerUser(mUserOneId, mUserOneService);
        BackupManagerService backupManagerService = createService();
        setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);

        expectThrows(
                SecurityException.class, () -> backupManagerService.adbRestore(mUserTwoId, null));
    }

    /**
     * Test that the backup service does not throw a {@link SecurityException} if the caller has
     * INTERACT_ACROSS_USERS_FULL permission and passes a different user id.
     */
    @Test
    public void testAdbRestore_withPermission_propagatesForNonCallingUser() throws Exception {
        registerUser(mUserOneId, mUserOneService);
        registerUser(mUserTwoId, mUserTwoService);
        BackupManagerService backupManagerService = createService();
        ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest();
        setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true);

        backupManagerService.adbRestore(mUserTwoId, parcelFileDescriptor);

        verify(mUserTwoService).adbRestore(parcelFileDescriptor);
    }

    /** Test that the backup service routes methods correctly to the user that requests it. */
    @Test
    public void testAdbRestore_onRegisteredUser_callsMethodForUser() throws Exception {
        registerUser(mUserOneId, mUserOneService);
        BackupManagerService backupManagerService = createService();
        ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest();
        setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);

        backupManagerService.adbRestore(mUserOneId, parcelFileDescriptor);

        verify(mUserOneService).adbRestore(parcelFileDescriptor);
    }

    /** Test that the backup service does not route methods for non-registered users. */
    @Test
    public void testAdbRestore_onUnknownUser_doesNotPropagateCall() throws Exception {
        registerUser(mUserOneId, mUserOneService);
        BackupManagerService backupManagerService = createService();
        ParcelFileDescriptor parcelFileDescriptor = getFileDescriptorForAdbTest();
        setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);

        backupManagerService.adbRestore(mUserTwoId, parcelFileDescriptor);

        verify(mUserOneService, never()).adbRestore(parcelFileDescriptor);
    }

    /** Test that the backup service routes methods correctly to the user that requests it. */
    @Test
    public void testAcknowledgeAdbBackupOrRestore_onRegisteredUser_callsMethodForUser()
            throws Exception {
        registerUser(mUserOneId, mUserOneService);
        BackupManagerService backupManagerService = createService();
        setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
        IFullBackupRestoreObserver observer = mock(IFullBackupRestoreObserver.class);

        backupManagerService.acknowledgeAdbBackupOrRestore(
                mUserOneId,
                /* token */ 0,
                /* allow */ true,
                "currentPassword",
                "encryptionPassword",
                observer);

        verify(mUserOneService)
                .acknowledgeAdbBackupOrRestore(
                        /* token */ 0,
                        /* allow */ true,
                        "currentPassword",
                        "encryptionPassword",
                        observer);
    }

    /** Test that the backup service does not route methods for non-registered users. */
    @Test
    public void testAcknowledgeAdbBackupOrRestore_onUnknownUser_doesNotPropagateCall()
            throws Exception {
        registerUser(mUserOneId, mUserOneService);
        BackupManagerService backupManagerService = createService();
        setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
        IFullBackupRestoreObserver observer = mock(IFullBackupRestoreObserver.class);

        backupManagerService.acknowledgeAdbBackupOrRestore(
                mUserTwoId,
                /* token */ 0,
                /* allow */ true,
                "currentPassword",
                "encryptionPassword",
                observer);

        verify(mUserOneService, never())
                .acknowledgeAdbBackupOrRestore(
                        /* token */ 0,
                        /* allow */ true,
                        "currentPassword",
                        "encryptionPassword",
                        observer);
    }

    // ---------------------------------------------
    //  Lifecycle tests
    // ---------------------------------------------
+313 −0

File changed.

Preview size limit exceeded, changes collapsed.

+0 −65

File changed.

Preview size limit exceeded, changes collapsed.