diff options
| author | Christopher Tate <ctate@google.com> | 2009-06-29 14:56:28 -0700 |
|---|---|---|
| committer | Christopher Tate <ctate@google.com> | 2009-06-29 15:33:27 -0700 |
| commit | 6ef58a1509b9d3348a33ca5686917796c2759aa5 (patch) | |
| tree | 0cdfef7bf8e2085dc2888c4222aba7481683ee2f | |
| parent | 3a608f829b54a7653c9cc2b3bdbda0641cca37bb (diff) | |
| download | frameworks_base-6ef58a1509b9d3348a33ca5686917796c2759aa5.zip frameworks_base-6ef58a1509b9d3348a33ca5686917796c2759aa5.tar.gz frameworks_base-6ef58a1509b9d3348a33ca5686917796c2759aa5.tar.bz2 | |
Implement persistent enable/disable of the backup manager
Backup & restore is still enabled by default, but with the expectation that it
will be enabled during the course of the Setup Wizard or some other privileged
entity that has notified the user about the ramifications. While disabled,
data-changed notices will still be collected, but no backup pass will be
scheduled. When the backup manager is later enabled, any pending data-changed
notices will then be processed and the apps invoked for backup.
| -rw-r--r-- | cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java | 55 | ||||
| -rw-r--r-- | core/java/android/backup/IBackupManager.aidl | 18 | ||||
| -rw-r--r-- | services/java/com/android/server/BackupManagerService.java | 68 |
3 files changed, 127 insertions, 14 deletions
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java index c3ddd20..c90b862 100644 --- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java @@ -62,6 +62,16 @@ public final class Bmgr { String op = args[0]; mNextArg = 1; + if ("enabled".equals(op)) { + doEnabled(); + return; + } + + if ("enable".equals(op)) { + doEnable(); + return; + } + if ("run".equals(op)) { doRun(); return; @@ -91,6 +101,41 @@ public final class Bmgr { showUsage(); } + private String enableToString(boolean enabled) { + return enabled ? "enabled" : "disabled"; + } + + private void doEnabled() { + try { + boolean isEnabled = mBmgr.isBackupEnabled(); + System.out.println("Backup Manager currently " + + enableToString(isEnabled)); + } catch (RemoteException e) { + System.err.println(e.toString()); + System.err.println(BMGR_NOT_RUNNING_ERR); + } + } + + private void doEnable() { + String arg = nextArg(); + if (arg == null) { + showUsage(); + return; + } + + try { + boolean enable = Boolean.parseBoolean(arg); + mBmgr.setBackupEnabled(enable); + System.out.println("Backup Manager now " + enableToString(enable)); + } catch (NumberFormatException e) { + showUsage(); + return; + } catch (RemoteException e) { + System.err.println(e.toString()); + System.err.println(BMGR_NOT_RUNNING_ERR); + } + } + private void doRun() { try { mBmgr.backupNow(); @@ -291,6 +336,8 @@ public final class Bmgr { private static void showUsage() { System.err.println("usage: bmgr [backup|restore|list|transport|run]"); System.err.println(" bmgr backup PACKAGE"); + System.err.println(" bmgr enable BOOL"); + System.err.println(" bmgr enabled"); System.err.println(" bmgr list transports"); System.err.println(" bmgr list sets"); System.err.println(" bmgr transport WHICH"); @@ -301,6 +348,14 @@ public final class Bmgr { System.err.println("Note that the backup pass will effectively be a no-op if the package"); System.err.println("does not actually have changed data to store."); System.err.println(""); + System.err.println("The 'enable' command enables or disables the entire backup mechanism."); + System.err.println("If the argument is 'true' it will be enabled, otherwise it will be"); + System.err.println("disabled. When disabled, neither backup or restore operations will"); + System.err.println("be performed."); + System.err.println(""); + System.err.println("The 'enabled' command reports the current enabled/disabled state of"); + System.err.println("the backup mechanism."); + System.err.println(""); System.err.println("The 'list transports' command reports the names of the backup transports"); System.err.println("currently available on the device. These names can be passed as arguments"); System.err.println("to the 'transport' command. The currently selected transport is indicated"); diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl index 39e160b..1f11762 100644 --- a/core/java/android/backup/IBackupManager.aidl +++ b/core/java/android/backup/IBackupManager.aidl @@ -48,6 +48,24 @@ interface IBackupManager { void agentDisconnected(String packageName); /** + * Enable/disable the backup service entirely. When disabled, no backup + * or restore operations will take place. Data-changed notifications will + * still be observed and collected, however, so that changes made while the + * mechanism was disabled will still be backed up properly if it is enabled + * at some point in the future. + * + * <p>Callers must hold the android.permission.BACKUP permission to use this method. + */ + void setBackupEnabled(boolean isEnabled); + + /** + * Report whether the backup mechanism is currently enabled. + * + * <p>Callers must hold the android.permission.BACKUP permission to use this method. + */ + boolean isBackupEnabled(); + + /** * Schedule an immediate backup attempt for all pending updates. This is * primarily intended for transports to use when they detect a suitable * opportunity for doing a backup pass. If there are no pending updates to diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 2b9ac4d..c67f0b5 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -74,6 +74,10 @@ class BackupManagerService extends IBackupManager.Stub { private static final String TAG = "BackupManagerService"; private static final boolean DEBUG = true; + // Persistent properties + private static final String BACKUP_TRANSPORT_PROPERTY = "persist.service.bkup.trans"; + private static final String BACKUP_ENABLED_PROPERTY = "persist.service.bkup.enabled"; + // Default time to wait after data changes before we back up the data private static final long COLLECTION_INTERVAL = 3 * 60 * 1000; @@ -86,10 +90,11 @@ class BackupManagerService extends IBackupManager.Stub { private Context mContext; private PackageManager mPackageManager; - private final IActivityManager mActivityManager; + private IActivityManager mActivityManager; + private boolean mEnabled; // access to this is synchronized on 'this' private final BackupHandler mBackupHandler = new BackupHandler(); // map UIDs to the set of backup client services within that UID's app set - private SparseArray<HashSet<ApplicationInfo>> mBackupParticipants + private final SparseArray<HashSet<ApplicationInfo>> mBackupParticipants = new SparseArray<HashSet<ApplicationInfo>>(); // set of backup services that have pending changes private class BackupRequest { @@ -128,7 +133,6 @@ class BackupManagerService extends IBackupManager.Stub { private volatile boolean mClearingData; // Transport bookkeeping - static private final String BACKUP_TRANSPORT_PROPERTY = "persist.service.bkup.trans"; private final HashMap<String,IBackupTransport> mTransports = new HashMap<String,IBackupTransport>(); private String mCurrentTransport; @@ -160,6 +164,9 @@ class BackupManagerService extends IBackupManager.Stub { mActivityManager = ActivityManagerNative.getDefault(); // Set up our bookkeeping + // !!! STOPSHIP: make this disabled by default so that we then gate on + // setupwizard or other opt-out UI + mEnabled = SystemProperties.getBoolean(BACKUP_ENABLED_PROPERTY, true); mBaseStateDir = new File(Environment.getDataDirectory(), "backup"); mDataDir = Environment.getDownloadCacheDirectory(); @@ -489,8 +496,15 @@ class BackupManagerService extends IBackupManager.Stub { // The queue lock should be held when scheduling a backup pass private void scheduleBackupPassLocked(long timeFromNowMillis) { - mBackupHandler.removeMessages(MSG_RUN_BACKUP); - mBackupHandler.sendEmptyMessageDelayed(MSG_RUN_BACKUP, timeFromNowMillis); + // We only schedule backups when we're actually enabled + synchronized (this) { + if (mEnabled) { + mBackupHandler.removeMessages(MSG_RUN_BACKUP); + mBackupHandler.sendEmptyMessageDelayed(MSG_RUN_BACKUP, timeFromNowMillis); + } else if (DEBUG) { + Log.v(TAG, "Disabled, so not scheduling backup pass"); + } + } } // Return the given transport @@ -1087,7 +1101,7 @@ class BackupManagerService extends IBackupManager.Stub { if (DEBUG) { int numKeys = mPendingBackups.size(); - Log.d(TAG, "Scheduling backup for " + numKeys + " participants:"); + Log.d(TAG, "Now awaiting backup for " + numKeys + " participants:"); for (BackupRequest b : mPendingBackups.values()) { Log.d(TAG, " + " + b + " agent=" + b.appInfo.backupAgentName); } @@ -1117,7 +1131,7 @@ class BackupManagerService extends IBackupManager.Stub { // Run a backup pass immediately for any applications that have declared // that they have pending updates. public void backupNow() throws RemoteException { - mContext.enforceCallingPermission("android.permission.BACKUP", "tryBackupNow"); + mContext.enforceCallingPermission("android.permission.BACKUP", "backupNow"); if (DEBUG) Log.v(TAG, "Scheduling immediate backup pass"); synchronized (mQueueLock) { @@ -1125,16 +1139,43 @@ class BackupManagerService extends IBackupManager.Stub { } } + // Enable/disable the backup transport + public void setBackupEnabled(boolean enable) { + mContext.enforceCallingPermission("android.permission.BACKUP", "setBackupEnabled"); + + boolean wasEnabled = mEnabled; + synchronized (this) { + SystemProperties.set(BACKUP_ENABLED_PROPERTY, enable ? "true" : "false"); + mEnabled = enable; + } + + if (enable && !wasEnabled) { + synchronized (mQueueLock) { + if (mPendingBackups.size() > 0) { + // !!! TODO: better policy around timing of the first backup pass + if (DEBUG) Log.v(TAG, "Backup enabled with pending data changes, scheduling"); + this.scheduleBackupPassLocked(COLLECTION_INTERVAL); + } + } + } +} + + // Report whether the backup mechanism is currently enabled + public boolean isBackupEnabled() { + mContext.enforceCallingPermission("android.permission.BACKUP", "isBackupEnabled"); + return mEnabled; // no need to synchronize just to read it + } + // Report the name of the currently active transport public String getCurrentTransport() { - mContext.enforceCallingPermission("android.permission.BACKUP", "selectBackupTransport"); + mContext.enforceCallingPermission("android.permission.BACKUP", "getCurrentTransport"); Log.v(TAG, "getCurrentTransport() returning " + mCurrentTransport); return mCurrentTransport; } // Report all known, available backup transports public String[] listAllTransports() { - mContext.enforceCallingPermission("android.permission.BACKUP", "selectBackupTransport"); + mContext.enforceCallingPermission("android.permission.BACKUP", "listAllTransports"); String[] list = null; ArrayList<String> known = new ArrayList<String>(); @@ -1292,7 +1333,8 @@ class BackupManagerService extends IBackupManager.Stub { synchronized (mQueueLock) { pw.println("Available transports:"); for (String t : listAllTransports()) { - pw.println(" " + t); + String pad = (t.equals(mCurrentTransport)) ? " * " : " "; + pw.println(pad + t); } int N = mBackupParticipants.size(); pw.println("Participants:"); @@ -1302,14 +1344,12 @@ class BackupManagerService extends IBackupManager.Stub { pw.println(uid); HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i); for (ApplicationInfo app: participants) { - pw.print(" "); - pw.println(app.toString()); + pw.println(" " + app.toString()); } } pw.println("Pending: " + mPendingBackups.size()); for (BackupRequest req : mPendingBackups.values()) { - pw.print(" "); - pw.println(req); + pw.println(" " + req); } } } |
