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

Commit 88e193ba authored by Chandan Nath's avatar Chandan Nath Committed by Android (Google) Code Review
Browse files

Merge "[Multi-user] Clean up user state stored in the system user directory when user is removed."

parents ff0e1f52 7053e28b
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -112,6 +112,11 @@ public class Bmgr {
            return;
        }

        if ("activated".equals(op)) {
            doActivated(userId);
            return;
        }

        if (!isBackupActive(userId)) {
            return;
        }
@@ -200,6 +205,21 @@ public class Bmgr {
        return true;
    }

    private String activatedToString(boolean activated) {
        return activated ? "activated" : "deactivated";
    }

    private void doActivated(@UserIdInt int userId) {
        try {
            System.out.println("Backup Manager currently "
                    + activatedToString(mBmgr.isBackupServiceActive(userId)));
        } catch (RemoteException e) {
            System.err.println(e.toString());
            System.err.println(BMGR_NOT_RUNNING_ERR);
        }

    }

    private String enableToString(boolean enabled) {
        return enabled ? "enabled" : "disabled";
    }
@@ -907,6 +927,7 @@ public class Bmgr {
        System.err.println("       bmgr cancel backups");
        System.err.println("       bmgr init TRANSPORT...");
        System.err.println("       bmgr activate BOOL");
        System.err.println("       bmgr activated");
        System.err.println("");
        System.err.println("The '--user' option specifies the user on which the operation is run.");
        System.err.println("It must be the first argument before the operation.");
@@ -978,6 +999,9 @@ public class Bmgr {
        System.err.println("If the argument is 'true' it will be activated, otherwise it will be");
        System.err.println("deactivated. When deactivated, the service will not be running and no");
        System.err.println("operations can be performed until activation.");
        System.err.println("");
        System.err.println("The 'activated' command reports the current activated/deactivated");
        System.err.println("state of the backup mechanism.");
    }

    private static class BackupMonitor extends IBackupManagerMonitor.Stub {
+33 −0
Original line number Diff line number Diff line
@@ -31,11 +31,14 @@ import android.app.backup.ISelectBackupTransportCallback;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.FileUtils;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -49,6 +52,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.SystemConfig;
import com.android.server.SystemService;

import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
@@ -86,6 +90,18 @@ public class BackupManagerService {

    private Set<ComponentName> mTransportWhitelist;

    private final BroadcastReceiver mUserRemovedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                if (userId > 0) { // for only non system users
                    onRemovedNonSystemUser(userId);
                }
            }
        }
    };

    /** Instantiate a new instance of {@link BackupManagerService}. */
    public BackupManagerService(
            Context context, Trampoline trampoline, HandlerThread backupThread) {
@@ -99,6 +115,23 @@ public class BackupManagerService {
        if (mTransportWhitelist == null) {
            mTransportWhitelist = Collections.emptySet();
        }

        mContext.registerReceiver(mUserRemovedReceiver,
                new IntentFilter(Intent.ACTION_USER_REMOVED));
    }

    /**
     * Remove backup state for non system {@code userId} when the user is removed from the device.
     * For non system users, backup state is stored in both the user's own dir and the system dir.
     * When the user is removed, the user's own dir gets removed by the OS. This method ensures that
     * the part of the user backup state which is in the system dir also gets removed.
     */
    private void onRemovedNonSystemUser(int userId) {
        Slog.i(TAG, "Removing state for non system user " + userId);
        File dir = UserBackupManagerFiles.getStateDirInSystemDir(userId);
        if (!FileUtils.deleteContentsAndDir(dir)) {
            Slog.w(TAG, "Failed to delete state dir for removed user: " + userId);
        }
    }

    /**
+9 −6
Original line number Diff line number Diff line
@@ -47,7 +47,6 @@ import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.DumpUtils;
import com.android.server.backup.utils.FileUtils;
import com.android.server.backup.utils.RandomAccessFileUtils;

import java.io.File;
@@ -95,7 +94,7 @@ public class Trampoline extends IBackupManager.Stub {
     * Name of file for non-system users that remembers whether backup was explicitly activated or
     * deactivated with a call to setBackupServiceActive.
     */
    private static final String REMEMBER_ACTIVATED_FILENAME_PREFIX = "backup-remember-activated";
    private static final String REMEMBER_ACTIVATED_FILENAME = "backup-remember-activated";

    // Product-level suppression of backup/restore.
    private static final String BACKUP_DISABLE_PROPERTY = "ro.backup.disable";
@@ -143,8 +142,7 @@ public class Trampoline extends IBackupManager.Stub {

    /** Stored in the system user's directory and the file is indexed by the user it refers to. */
    protected File getRememberActivatedFileForNonSystemUser(int userId) {
        return FileUtils.createNewFile(UserBackupManagerFiles.getStateFileInSystemDir(
                REMEMBER_ACTIVATED_FILENAME_PREFIX, 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. */
@@ -336,8 +334,13 @@ public class Trampoline extends IBackupManager.Stub {
        // action since we need to remember that a permissioned call was made irrespective of
        // whether the call changes the state or not.
        if (userId != UserHandle.USER_SYSTEM) {
            RandomAccessFileUtils.writeBoolean(getRememberActivatedFileForNonSystemUser(userId),
                    makeActive);
            try {
                File rememberFile = getRememberActivatedFileForNonSystemUser(userId);
                createFile(rememberFile);
                RandomAccessFileUtils.writeBoolean(rememberFile, makeActive);
            } catch (IOException e) {
                Slog.e(TAG, "Unable to persist backup service activity", e);
            }
        }

        if (mGlobalDisable) {
+8 −3
Original line number Diff line number Diff line
@@ -49,8 +49,13 @@ final class UserBackupManagerFiles {
        return new File(Environment.getDownloadCacheDirectory(), BACKUP_STAGING_DIR);
    }

    /** Stored in the system user's directory and the file is indexed by the user it refers to. */
    static File getStateFileInSystemDir(String prefix, int userId) {
        return new File(getBaseStateDir(UserHandle.USER_SYSTEM), prefix + "-" + userId);
    /** A user specific dir within the system user's directory. */
    static File getStateDirInSystemDir(int userId) {
        return new File(getBaseStateDir(UserHandle.USER_SYSTEM), "" + userId);
    }

    /** Stored in a user specific dir within the system user's directory. */
    static File getStateFileInSystemDir(String filename, int userId) {
        return new File(getStateDirInSystemDir(userId), filename);
    }
}