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

Commit 87fb5b58 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "BackupManagerService: Fix global backup toggle to restart user services" into main

parents 4bee8c55 783153c1
Loading
Loading
Loading
Loading
+68 −25
Original line number Diff line number Diff line
@@ -500,9 +500,18 @@ public class BackupManagerService extends IBackupManager.Stub implements BackupM
    }

    /**
     * Sets the active state of the backup service for a given user.
     *
     * This method is the entry point for activating or deactivating the backup service. It
     * enforces the necessary permissions and then delegates to helper methods to handle the logic.
     * If the call is for the system user, it acts as a global toggle for all users.
     *
     * Only privileged callers should be changing the backup state. Deactivating backup in the
     * system user also deactivates backup in all users. We are not guaranteed that {@code userId}
     * is unlocked at this point yet, so handle both cases.
     *
     * @param userId The user for whom to change the backup service's state.
     * @param makeActive {@code true} to activate the service, {@code false} to deactivate it.
     */
    public void setBackupServiceActive(@UserIdInt int userId, boolean makeActive) {
        enforceSetBackupServiceActiveAllowedForUser(userId);
@@ -531,19 +540,26 @@ public class BackupManagerService extends IBackupManager.Stub implements BackupM
        }

        synchronized (mLock) {
            Slog.i(TAG, "Making backup " + (makeActive ? "" : "in") + "active");
            Slog.i(TAG, "Making backup " + (makeActive ? "" : "in") + "active for user " + userId);
            if (makeActive) {
                handleBackupActivationLocked(userId);
            } else {
                handleBackupDeactivationLocked(userId);
            }
        }
    }

    @GuardedBy("mLock")
    private void handleBackupActivationLocked(@UserIdInt int userId) {
        try {
            activateBackupForUserLocked(userId);
        } catch (IOException e) {
            Slog.e(TAG, "Unable to persist backup service activity");
        }

                // If the user is unlocked, we can start the backup service for it. Otherwise we
                // will start the service when the user is unlocked as part of its unlock callback.
        // Enabling for a single user.
        if (userId != UserHandle.USER_SYSTEM) {
            if (mUserManagerInternal.isUserUnlocked(userId)) {
                    // Clear calling identity as initialization enforces the system identity but we
                    // can be coming from shell.
                final long oldId = Binder.clearCallingIdentity();
                try {
                    startServiceForUser(userId);
@@ -551,17 +567,44 @@ public class BackupManagerService extends IBackupManager.Stub implements BackupM
                    Binder.restoreCallingIdentity(oldId);
                }
            }
            } else {
            return;
        }

        // Globally enabling. Start services for all running users.
        final long oldId = Binder.clearCallingIdentity();
        try {
            List<UserInfo> users = mUserManagerInternal.getUsers(/* excludeDying */ true);
            for (UserInfo user : users) {
                if (mUserManagerInternal.isUserRunning(user.id)) {
                    startServiceForUser(user.id);
                }
            }
        } finally {
            Binder.restoreCallingIdentity(oldId);
        }
    }

    @GuardedBy("mLock")
    private void handleBackupDeactivationLocked(@UserIdInt int userId) {
        try {
                    //TODO(b/121198006): what if this throws an exception?
            deactivateBackupForUserLocked(userId);
        } catch (IOException e) {
            Slog.e(TAG, "Unable to persist backup service inactivity");
        }
                //TODO(b/121198006): loop through active users that have work profile and
                // stop them as well.

        // Disabling for a single user.
        if (userId != UserHandle.USER_SYSTEM) {
            onStopUser(userId);
            return;
        }

        // Globally disabling. Stop services for all running users.
        int[] userIdsToStop = new int[mUserServices.size()];
        for (int i = 0; i < mUserServices.size(); i++) {
            userIdsToStop[i] = mUserServices.keyAt(i);
        }
        for (int userToStop : userIdsToStop) {
            onStopUser(userToStop);
        }
    }

+26 −0
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@@ -575,6 +576,31 @@ public class BackupManagerServiceTest {
        assertFalse(getFakeActivatedFileForUser(NON_SYSTEM_USER).exists());
    }

    @Test
    public void setBackupServiceActive_globallyToggled_restartsUserService() {
        // Start with a non-system user's backup service running.
        createBackupManagerServiceAndUnlockSystemUser();
        mService.setBackupServiceActive(NON_SYSTEM_USER, true);
        simulateUserUnlocked(NON_SYSTEM_USER);
        assertTrue(mService.isUserReadyForBackup(NON_SYSTEM_USER));

        // Mock the running users for the global toggle.
        UserInfo systemUserInfo = new UserInfo(UserHandle.USER_SYSTEM, "system", 0);
        UserInfo nonSystemUserInfo = new UserInfo(NON_SYSTEM_USER, "non-system", 0);
        when(mUserManagerInternalMock.getUsers(true))
                .thenReturn(Arrays.asList(systemUserInfo, nonSystemUserInfo));
        when(mUserManagerInternalMock.isUserRunning(UserHandle.USER_SYSTEM)).thenReturn(true);
        when(mUserManagerInternalMock.isUserRunning(NON_SYSTEM_USER)).thenReturn(true);

        // Disable backup globally. This should stop the user's service.
        mService.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
        assertFalse(mService.isUserReadyForBackup(NON_SYSTEM_USER));

        // Re-enable backup globally. This should restart the user's service.
        mService.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
        assertTrue(mService.isUserReadyForBackup(NON_SYSTEM_USER));
    }

    @Test
    public void setBackupServiceActive_forOneNonSystemUser_doesNotActivateForAllNonSystemUsers() {
        createBackupManagerServiceAndUnlockSystemUser();