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

Commit 5b17f4e5 authored by [CSarp Misoglu's avatar [CSarp Misoglu Committed by Sarp Misoglu
Browse files

Make B&R active for the main user in headless mode

In this CL we are introducing the concept of a 'default' backup user, for whom backup is activated by default. Basically, if there is a 'main' user on the device, it will be the default user. Otherwise it will be the system user. Note that the main user can be the system user (at least in theory). And if there is a main user that isn't the system user, backup will be deactivated for the system user.

Backup is deactivated by the main user by creating a 'suppress' file for it, just like it worked before for the system user.

There was a previous behavior where if backup was deactivated for the system user, it would be deactivated for every user. I think this was to allow DevicePolicyManager to disable all backups on the device. We maintain this behavior, so if `satBackupService(USER_SYSTEM)` is called, backup will be disabled for ALL users-- even the default user.

To properly test this, mocking a static method was required. This is only possible with extended Mockito, which is enabled in `mockingservicetests` so `BackupManagerServiceTest` is moved there. I also revamped most of the tests in there to be more concise and less... weird (there were a bunch of tests that didn't actually test anything).

Test: BackupManagerServiceTest
Bug: 259850130
Change-Id: Iec8b43d1e3560fe40b70bebfd37db1b2e5b0f9ca
parent 77cbd50b
Loading
Loading
Loading
Loading
+73 −26
Original line number Diff line number Diff line
@@ -156,6 +156,16 @@ public class BackupManagerService extends IBackupManager.Stub {
        }
    };

    /**
     * The user that the backup is activated by default for.
     *
     * If there is a {@link UserManager#getMainUser()}, this will be that user. If not, it will be
     * {@link UserHandle#USER_SYSTEM}.
     *
     * @see #isBackupActivatedForUser(int)
     */
    @UserIdInt private final int mDefaultBackupUserId;

    public BackupManagerService(Context context) {
        this(context, new SparseArray<>());
    }
@@ -175,6 +185,8 @@ public class BackupManagerService extends IBackupManager.Stub {
        mTransportWhitelist = (transportWhitelist == null) ? emptySet() : transportWhitelist;
        mContext.registerReceiver(
                mUserRemovedReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED));
        UserHandle mainUser = getUserManager().getMainUser();
        mDefaultBackupUserId = mainUser == null ? UserHandle.USER_SYSTEM : mainUser.getIdentifier();
    }

    // TODO: Remove this when we implement DI by injecting in the construtor.
@@ -183,31 +195,35 @@ public class BackupManagerService extends IBackupManager.Stub {
        return mHandler;
    }

    @VisibleForTesting
    protected boolean isBackupDisabled() {
        return SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false);
    }

    @VisibleForTesting
    protected int binderGetCallingUserId() {
        return Binder.getCallingUserHandle().getIdentifier();
    }

    @VisibleForTesting
    protected int binderGetCallingUid() {
        return Binder.getCallingUid();
    }

    /** Stored in the system user's directory. */
    protected File getSuppressFileForSystemUser() {
        return new File(UserBackupManagerFiles.getBaseStateDir(UserHandle.USER_SYSTEM),
                BACKUP_SUPPRESS_FILENAME);
    @VisibleForTesting
    protected File getSuppressFileForUser(@UserIdInt int userId) {
        return new File(UserBackupManagerFiles.getBaseStateDir(userId), BACKUP_SUPPRESS_FILENAME);
    }

    /** Stored in the system user's directory and the file is indexed by the user it refers to. */
    @VisibleForTesting
    protected File getRememberActivatedFileForNonSystemUser(int userId) {
        return UserBackupManagerFiles.getStateFileInSystemDir(REMEMBER_ACTIVATED_FILENAME, userId);
    }

    /** Stored in the system user's directory and the file is indexed by the user it refers to. */
    protected File getActivatedFileForNonSystemUser(int userId) {
    @VisibleForTesting
    protected File getActivatedFileForUser(int userId) {
        return UserBackupManagerFiles.getStateFileInSystemDir(BACKUP_ACTIVATED_FILENAME, userId);
    }

@@ -249,31 +265,40 @@ public class BackupManagerService extends IBackupManager.Stub {
    }

    /**
     * Deactivates the backup service for user {@code userId}. If this is the system user, it
     * creates a suppress file which disables backup for all users. If this is a non-system user, it
     * only deactivates backup for that user by deleting its activate file.
     * Deactivates the backup service for user {@code userId}.
     *
     * If this is the system user or the {@link #mDefaultBackupUserId} user, it creates a "suppress"
     * file for this user.
     *
     * Otherwise, it deleties the user's "activated" file.
     *
     * Note that if backup is deactivated for the system user, it will be deactivated for ALL
     * users until it is reactivated for the system user, at which point the per-user activation
     * status will be the source of truth.
     */
    @GuardedBy("mStateLock")
    private void deactivateBackupForUserLocked(int userId) throws IOException {
        if (userId == UserHandle.USER_SYSTEM) {
            createFile(getSuppressFileForSystemUser());
        if (userId == UserHandle.USER_SYSTEM || userId == mDefaultBackupUserId) {
            createFile(getSuppressFileForUser(userId));
        } else {
            deleteFile(getActivatedFileForNonSystemUser(userId));
            deleteFile(getActivatedFileForUser(userId));
        }
    }

    /**
     * Enables the backup service for user {@code userId}. If this is the system user, it deletes
     * the suppress file. If this is a non-system user, it creates the user's activate file. Note,
     * deleting the suppress file does not automatically enable backup for non-system users, they
     * need their own activate file in order to participate in the service.
     * Activates the backup service for user {@code userId}.
     *
     * If this is the system user or the {@link #mDefaultBackupUserId} user, it deletes its
     * "suppress" file.
     *
     * Otherwise, it creates the user's "activated" file.
     */
    @GuardedBy("mStateLock")
    private void activateBackupForUserLocked(int userId) throws IOException {
        if (userId == UserHandle.USER_SYSTEM) {
            deleteFile(getSuppressFileForSystemUser());
        if (userId == UserHandle.USER_SYSTEM || userId == mDefaultBackupUserId) {
            deleteFile(getSuppressFileForUser(userId));
        } else {
            createFile(getActivatedFileForNonSystemUser(userId));
            createFile(getActivatedFileForUser(userId));
        }
    }

@@ -286,32 +311,52 @@ public class BackupManagerService extends IBackupManager.Stub {
    @Override
    public boolean isUserReadyForBackup(int userId) {
        enforceCallingPermissionOnUserId(userId, "isUserReadyForBackup()");
        return mUserServices.get(UserHandle.USER_SYSTEM) != null
                && mUserServices.get(userId) != null;
        return mUserServices.get(userId) != null;
    }

    /**
     * Backup is activated for the system user if the suppress file does not exist. Backup is
     * activated for non-system users if the suppress file does not exist AND the user's activated
     * file exists.
     * If there is a "suppress" file for the system user, backup is inactive for ALL users.
     *
     * Otherwise, the below logic applies:
     *
     * For the {@link #mDefaultBackupUserId}, backup is active by default. Backup is only
     * deactivated if there exists a "suppress" file for the user, which can be created by calling
     * {@link #setBackupServiceActive}.
     *
     * For non-main users, backup is only active if there exists an "activated" file for the user,
     * which can also be created by calling {@link #setBackupServiceActive}.
     */
    private boolean isBackupActivatedForUser(int userId) {
        if (getSuppressFileForSystemUser().exists()) {
        if (getSuppressFileForUser(UserHandle.USER_SYSTEM).exists()) {
            return false;
        }

        boolean isDefaultUser = userId == mDefaultBackupUserId;

        // If the default user is not the system user, we are in headless mode and the system user
        // doesn't have an actual human user associated with it.
        if ((userId == UserHandle.USER_SYSTEM) && !isDefaultUser) {
            return false;
        }

        return userId == UserHandle.USER_SYSTEM
                || getActivatedFileForNonSystemUser(userId).exists();
        if (isDefaultUser && getSuppressFileForUser(userId).exists()) {
            return false;
        }

        return isDefaultUser || getActivatedFileForUser(userId).exists();
    }

    @VisibleForTesting
    protected Context getContext() {
        return mContext;
    }

    @VisibleForTesting
    protected UserManager getUserManager() {
        return mUserManager;
    }

    @VisibleForTesting
    protected void postToHandler(Runnable runnable) {
        mHandler.post(runnable);
    }
@@ -322,6 +367,7 @@ public class BackupManagerService extends IBackupManager.Stub {
     * the handler thread {@link #mHandlerThread} to keep unlock time low since backup is not
     * essential for device functioning.
     */
    @VisibleForTesting
    void onUnlockUser(int userId) {
        postToHandler(() -> startServiceForUser(userId));
    }
@@ -357,6 +403,7 @@ public class BackupManagerService extends IBackupManager.Stub {
     * Starts the backup service for user {@code userId} by registering its instance of {@link
     * UserBackupManagerService} with this service and setting enabled state.
     */
    @VisibleForTesting
    void startServiceForUser(int userId, UserBackupManagerService userBackupManagerService) {
        mUserServices.put(userId, userBackupManagerService);

+256 −180

File changed and moved.

Preview size limit exceeded, changes collapsed.