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

Commit ab4748c6 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 5694 into donut

* changes:
  Implement persistent enable/disable of the backup manager
parents 48d4f673 6ef58a15
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -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");
+18 −0
Original line number Diff line number Diff line
@@ -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
+54 −14
Original line number Diff line number Diff line
@@ -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) {
        // 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);
            }
        }
    }