diff options
4 files changed, 74 insertions, 9 deletions
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java index 98ab6665958c..680ccfc57ddf 100644 --- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java @@ -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 { diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 7106664d0699..79afe8e4de72 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -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); + } } /** diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java index bb0aba0c2e88..a9b292b37903 100644 --- a/services/backup/java/com/android/server/backup/Trampoline.java +++ b/services/backup/java/com/android/server/backup/Trampoline.java @@ -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) { diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerFiles.java b/services/backup/java/com/android/server/backup/UserBackupManagerFiles.java index 4638ac63de4a..8e605426d0c9 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerFiles.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerFiles.java @@ -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); } } |