Loading cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +24 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,11 @@ public class Bmgr { return; } if ("activated".equals(op)) { doActivated(userId); return; } if (!isBackupActive(userId)) { return; } Loading Loading @@ -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"; } Loading Loading @@ -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."); Loading Loading @@ -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 { Loading services/backup/java/com/android/server/backup/BackupManagerService.java +33 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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); } } /** Loading services/backup/java/com/android/server/backup/Trampoline.java +9 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"; Loading Loading @@ -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. */ Loading Loading @@ -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) { Loading services/backup/java/com/android/server/backup/UserBackupManagerFiles.java +8 −3 Original line number Diff line number Diff line Loading @@ -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); } } Loading
cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +24 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,11 @@ public class Bmgr { return; } if ("activated".equals(op)) { doActivated(userId); return; } if (!isBackupActive(userId)) { return; } Loading Loading @@ -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"; } Loading Loading @@ -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."); Loading Loading @@ -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 { Loading
services/backup/java/com/android/server/backup/BackupManagerService.java +33 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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); } } /** Loading
services/backup/java/com/android/server/backup/Trampoline.java +9 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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"; Loading Loading @@ -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. */ Loading Loading @@ -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) { Loading
services/backup/java/com/android/server/backup/UserBackupManagerFiles.java +8 −3 Original line number Diff line number Diff line Loading @@ -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); } }