Merge change 5694 into donut
* changes: Implement persistent enable/disable of the backup manager
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -47,6 +47,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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user