Loading cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +26 −6 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ import android.app.backup.IRestoreSession; import android.os.RemoteException; import android.os.ServiceManager; import java.util.HashSet; public final class Bmgr { IBackupManager mBmgr; IRestoreSession mRestore; Loading @@ -45,7 +47,6 @@ public final class Bmgr { } public void run(String[] args) { boolean validCommand = false; if (args.length < 1) { showUsage(); return; Loading Loading @@ -329,7 +330,13 @@ public final class Bmgr { } else { try { long token = Long.parseLong(arg, 16); doRestoreAll(token); HashSet<String> filter = null; while ((arg = nextArg()) != null) { if (filter == null) filter = new HashSet<String>(); filter.add(arg); } doRestoreAll(token, filter); } catch (NumberFormatException e) { showUsage(); return; Loading Loading @@ -364,7 +371,7 @@ public final class Bmgr { } } private void doRestoreAll(long token) { private void doRestoreAll(long token, HashSet<String> filter) { RestoreObserver observer = new RestoreObserver(); try { Loading @@ -383,7 +390,13 @@ public final class Bmgr { for (RestoreSet s : sets) { if (s.token == token) { System.out.println("Scheduling restore: " + s.name); if (filter == null) { didRestore = (mRestore.restoreAll(token, observer) == 0); } else { String[] names = new String[filter.size()]; filter.toArray(names); didRestore = (mRestore.restoreSome(token, observer, names) == 0); } break; } } Loading Loading @@ -430,6 +443,7 @@ public final class Bmgr { System.err.println(" bmgr list sets"); System.err.println(" bmgr transport WHICH"); System.err.println(" bmgr restore TOKEN"); System.err.println(" bmgr restore TOKEN PACKAGE..."); System.err.println(" bmgr restore PACKAGE"); System.err.println(" bmgr run"); System.err.println(" bmgr wipe PACKAGE"); Loading Loading @@ -457,12 +471,18 @@ public final class Bmgr { System.err.println("The 'transport' command designates the named transport as the currently"); System.err.println("active one. This setting is persistent across reboots."); System.err.println(""); System.err.println("The 'restore' command when given a restore token initiates a full-system"); System.err.println("The 'restore' command when given just a restore token initiates a full-system"); System.err.println("restore operation from the currently active transport. It will deliver"); System.err.println("the restore set designated by the TOKEN argument to each application"); System.err.println("that had contributed data to that restore set."); System.err.println(""); System.err.println("The 'restore' command when given a package name intiates a restore of"); System.err.println("The 'restore' command when given a token and one or more package names"); System.err.println("initiates a restore operation of just those given packages from the restore"); System.err.println("set designated by the TOKEN argument. It is effectively the same as the"); System.err.println("'restore' operation supplying only a token, but applies a filter to the"); System.err.println("set of applications to be restored."); System.err.println(""); System.err.println("The 'restore' command when given just a package name intiates a restore of"); System.err.println("just that one package according to the restore set selection algorithm"); System.err.println("used by the RestoreSession.restorePackage() method."); System.err.println(""); Loading core/java/android/app/backup/IRestoreSession.aidl +19 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,25 @@ interface IRestoreSession { */ int restoreAll(long token, IRestoreObserver observer); /** * Restore select packages from the given set onto the device, replacing the * current data of any app contained in the set with the data previously * backed up. * * <p>Callers must hold the android.permission.BACKUP permission to use this method. * * @return Zero on success, nonzero on error. The observer will only receive * progress callbacks if this method returned zero. * @param token The token from {@link getAvailableRestoreSets()} corresponding to * the restore set that should be used. * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. * @param packages The set of packages for which to attempt a restore. Regardless of * the contents of the actual back-end dataset named by {@code token}, only * applications mentioned in this list will have their data restored. */ int restoreSome(long token, IRestoreObserver observer, in String[] packages); /** * Restore a single application from backup. The data will be restored from the * current backup dataset if the given package has stored data there, or from Loading core/java/android/app/backup/RestoreSession.java +34 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,40 @@ public class RestoreSession { return err; } /** * Restore select packages from the given set onto the device, replacing the * current data of any app contained in the set with the data previously * backed up. * * <p>Callers must hold the android.permission.BACKUP permission to use this method. * * @return Zero on success, nonzero on error. The observer will only receive * progress callbacks if this method returned zero. * @param token The token from {@link getAvailableRestoreSets()} corresponding to * the restore set that should be used. * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. * @param packages The set of packages for which to attempt a restore. Regardless of * the contents of the actual back-end dataset named by {@code token}, only * applications mentioned in this list will have their data restored. * * @hide */ public int restoreSome(long token, RestoreObserver observer, String[] packages) { int err = -1; if (mObserver != null) { Log.d(TAG, "restoreAll() called during active restore"); return -1; } mObserver = new RestoreObserverWrapper(mContext, observer); try { err = mBinder.restoreSome(token, mObserver, packages); } catch (RemoteException e) { Log.d(TAG, "Can't contact server to restore packages"); } return err; } /** * Restore a single application from backup. The data will be restored from the * current backup dataset if the given package has stored data there, or from Loading services/java/com/android/server/BackupManagerService.java +105 −3 Original line number Diff line number Diff line Loading @@ -224,6 +224,7 @@ class BackupManagerService extends IBackupManager.Stub { public PackageInfo pkgInfo; public int pmToken; // in post-install restore, the PM's token for this transaction public boolean needFullBackup; public String[] filterSet; RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, PackageInfo _pkg, int _pmToken, boolean _needFullBackup) { Loading @@ -233,6 +234,7 @@ class BackupManagerService extends IBackupManager.Stub { pkgInfo = _pkg; pmToken = _pmToken; needFullBackup = _needFullBackup; filterSet = null; } RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, Loading @@ -243,6 +245,18 @@ class BackupManagerService extends IBackupManager.Stub { pkgInfo = null; pmToken = 0; needFullBackup = _needFullBackup; filterSet = null; } RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, String[] _filterSet, boolean _needFullBackup) { transport = _transport; observer = _obs; token = _token; pkgInfo = null; pmToken = 0; needFullBackup = _needFullBackup; filterSet = _filterSet; } } Loading Loading @@ -404,7 +418,7 @@ class BackupManagerService extends IBackupManager.Stub { Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer); (new PerformRestoreTask(params.transport, params.observer, params.token, params.pkgInfo, params.pmToken, params.needFullBackup)).run(); params.needFullBackup, params.filterSet)).run(); break; } Loading Loading @@ -3020,6 +3034,7 @@ class BackupManagerService extends IBackupManager.Stub { private File mStateDir; private int mPmToken; private boolean mNeedFullBackup; private HashSet<String> mFilterSet; class RestoreRequest { public PackageInfo app; Loading @@ -3033,7 +3048,7 @@ class BackupManagerService extends IBackupManager.Stub { PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer, long restoreSetToken, PackageInfo targetPackage, int pmToken, boolean needFullBackup) { boolean needFullBackup, String[] filterSet) { mTransport = transport; mObserver = observer; mToken = restoreSetToken; Loading @@ -3041,6 +3056,15 @@ class BackupManagerService extends IBackupManager.Stub { mPmToken = pmToken; mNeedFullBackup = needFullBackup; if (filterSet != null) { mFilterSet = new HashSet<String>(); for (String pkg : filterSet) { mFilterSet.add(pkg); } } else { mFilterSet = null; } try { mStateDir = new File(mBaseStateDir, transport.transportDirName()); } catch (RemoteException e) { Loading @@ -3052,7 +3076,8 @@ class BackupManagerService extends IBackupManager.Stub { long startRealtime = SystemClock.elapsedRealtime(); if (DEBUG) Slog.v(TAG, "Beginning restore process mTransport=" + mTransport + " mObserver=" + mObserver + " mToken=" + Long.toHexString(mToken) + " mTargetPackage=" + mTargetPackage + " mPmToken=" + mPmToken); + " mTargetPackage=" + mTargetPackage + " mFilterSet=" + mFilterSet + " mPmToken=" + mPmToken); PackageManagerBackupAgent pmAgent = null; int error = -1; // assume error Loading @@ -3071,6 +3096,22 @@ class BackupManagerService extends IBackupManager.Stub { List<PackageInfo> agentPackages = allAgentPackages(); if (mTargetPackage == null) { // if there's a filter set, strip out anything that isn't // present before proceeding if (mFilterSet != null) { for (int i = agentPackages.size() - 1; i >= 0; i--) { final PackageInfo pkg = agentPackages.get(i); if (! mFilterSet.contains(pkg.packageName)) { agentPackages.remove(i); } } if (DEBUG) { Slog.i(TAG, "Post-filter package set for restore:"); for (PackageInfo p : agentPackages) { Slog.i(TAG, " " + p); } } } restorePackages.addAll(agentPackages); } else { // Just one package to attempt restore of Loading Loading @@ -4266,6 +4307,67 @@ class BackupManagerService extends IBackupManager.Stub { return -1; } public synchronized int restoreSome(long token, IRestoreObserver observer, String[] packages) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "performRestore"); if (DEBUG) { StringBuilder b = new StringBuilder(128); b.append("restoreSome token="); b.append(Long.toHexString(token)); b.append(" observer="); b.append(observer.toString()); b.append(" packages="); if (packages == null) { b.append("null"); } else { b.append('{'); boolean first = true; for (String s : packages) { if (!first) { b.append(", "); } else first = false; b.append(s); } b.append('}'); } Slog.d(TAG, b.toString()); } if (mEnded) { throw new IllegalStateException("Restore session already ended"); } if (mRestoreTransport == null || mRestoreSets == null) { Slog.e(TAG, "Ignoring restoreAll() with no restore set"); return -1; } if (mPackageName != null) { Slog.e(TAG, "Ignoring restoreAll() on single-package session"); return -1; } synchronized (mQueueLock) { for (int i = 0; i < mRestoreSets.length; i++) { if (token == mRestoreSets[i].token) { long oldId = Binder.clearCallingIdentity(); mWakelock.acquire(); Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); msg.obj = new RestoreParams(mRestoreTransport, observer, token, packages, true); mBackupHandler.sendMessage(msg); Binder.restoreCallingIdentity(oldId); return 0; } } } Slog.w(TAG, "Restore token " + Long.toHexString(token) + " not found"); return -1; } public synchronized int restorePackage(String packageName, IRestoreObserver observer) { if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer); Loading Loading
cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +26 −6 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ import android.app.backup.IRestoreSession; import android.os.RemoteException; import android.os.ServiceManager; import java.util.HashSet; public final class Bmgr { IBackupManager mBmgr; IRestoreSession mRestore; Loading @@ -45,7 +47,6 @@ public final class Bmgr { } public void run(String[] args) { boolean validCommand = false; if (args.length < 1) { showUsage(); return; Loading Loading @@ -329,7 +330,13 @@ public final class Bmgr { } else { try { long token = Long.parseLong(arg, 16); doRestoreAll(token); HashSet<String> filter = null; while ((arg = nextArg()) != null) { if (filter == null) filter = new HashSet<String>(); filter.add(arg); } doRestoreAll(token, filter); } catch (NumberFormatException e) { showUsage(); return; Loading Loading @@ -364,7 +371,7 @@ public final class Bmgr { } } private void doRestoreAll(long token) { private void doRestoreAll(long token, HashSet<String> filter) { RestoreObserver observer = new RestoreObserver(); try { Loading @@ -383,7 +390,13 @@ public final class Bmgr { for (RestoreSet s : sets) { if (s.token == token) { System.out.println("Scheduling restore: " + s.name); if (filter == null) { didRestore = (mRestore.restoreAll(token, observer) == 0); } else { String[] names = new String[filter.size()]; filter.toArray(names); didRestore = (mRestore.restoreSome(token, observer, names) == 0); } break; } } Loading Loading @@ -430,6 +443,7 @@ public final class Bmgr { System.err.println(" bmgr list sets"); System.err.println(" bmgr transport WHICH"); System.err.println(" bmgr restore TOKEN"); System.err.println(" bmgr restore TOKEN PACKAGE..."); System.err.println(" bmgr restore PACKAGE"); System.err.println(" bmgr run"); System.err.println(" bmgr wipe PACKAGE"); Loading Loading @@ -457,12 +471,18 @@ public final class Bmgr { System.err.println("The 'transport' command designates the named transport as the currently"); System.err.println("active one. This setting is persistent across reboots."); System.err.println(""); System.err.println("The 'restore' command when given a restore token initiates a full-system"); System.err.println("The 'restore' command when given just a restore token initiates a full-system"); System.err.println("restore operation from the currently active transport. It will deliver"); System.err.println("the restore set designated by the TOKEN argument to each application"); System.err.println("that had contributed data to that restore set."); System.err.println(""); System.err.println("The 'restore' command when given a package name intiates a restore of"); System.err.println("The 'restore' command when given a token and one or more package names"); System.err.println("initiates a restore operation of just those given packages from the restore"); System.err.println("set designated by the TOKEN argument. It is effectively the same as the"); System.err.println("'restore' operation supplying only a token, but applies a filter to the"); System.err.println("set of applications to be restored."); System.err.println(""); System.err.println("The 'restore' command when given just a package name intiates a restore of"); System.err.println("just that one package according to the restore set selection algorithm"); System.err.println("used by the RestoreSession.restorePackage() method."); System.err.println(""); Loading
core/java/android/app/backup/IRestoreSession.aidl +19 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,25 @@ interface IRestoreSession { */ int restoreAll(long token, IRestoreObserver observer); /** * Restore select packages from the given set onto the device, replacing the * current data of any app contained in the set with the data previously * backed up. * * <p>Callers must hold the android.permission.BACKUP permission to use this method. * * @return Zero on success, nonzero on error. The observer will only receive * progress callbacks if this method returned zero. * @param token The token from {@link getAvailableRestoreSets()} corresponding to * the restore set that should be used. * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. * @param packages The set of packages for which to attempt a restore. Regardless of * the contents of the actual back-end dataset named by {@code token}, only * applications mentioned in this list will have their data restored. */ int restoreSome(long token, IRestoreObserver observer, in String[] packages); /** * Restore a single application from backup. The data will be restored from the * current backup dataset if the given package has stored data there, or from Loading
core/java/android/app/backup/RestoreSession.java +34 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,40 @@ public class RestoreSession { return err; } /** * Restore select packages from the given set onto the device, replacing the * current data of any app contained in the set with the data previously * backed up. * * <p>Callers must hold the android.permission.BACKUP permission to use this method. * * @return Zero on success, nonzero on error. The observer will only receive * progress callbacks if this method returned zero. * @param token The token from {@link getAvailableRestoreSets()} corresponding to * the restore set that should be used. * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. * @param packages The set of packages for which to attempt a restore. Regardless of * the contents of the actual back-end dataset named by {@code token}, only * applications mentioned in this list will have their data restored. * * @hide */ public int restoreSome(long token, RestoreObserver observer, String[] packages) { int err = -1; if (mObserver != null) { Log.d(TAG, "restoreAll() called during active restore"); return -1; } mObserver = new RestoreObserverWrapper(mContext, observer); try { err = mBinder.restoreSome(token, mObserver, packages); } catch (RemoteException e) { Log.d(TAG, "Can't contact server to restore packages"); } return err; } /** * Restore a single application from backup. The data will be restored from the * current backup dataset if the given package has stored data there, or from Loading
services/java/com/android/server/BackupManagerService.java +105 −3 Original line number Diff line number Diff line Loading @@ -224,6 +224,7 @@ class BackupManagerService extends IBackupManager.Stub { public PackageInfo pkgInfo; public int pmToken; // in post-install restore, the PM's token for this transaction public boolean needFullBackup; public String[] filterSet; RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, PackageInfo _pkg, int _pmToken, boolean _needFullBackup) { Loading @@ -233,6 +234,7 @@ class BackupManagerService extends IBackupManager.Stub { pkgInfo = _pkg; pmToken = _pmToken; needFullBackup = _needFullBackup; filterSet = null; } RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, Loading @@ -243,6 +245,18 @@ class BackupManagerService extends IBackupManager.Stub { pkgInfo = null; pmToken = 0; needFullBackup = _needFullBackup; filterSet = null; } RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, String[] _filterSet, boolean _needFullBackup) { transport = _transport; observer = _obs; token = _token; pkgInfo = null; pmToken = 0; needFullBackup = _needFullBackup; filterSet = _filterSet; } } Loading Loading @@ -404,7 +418,7 @@ class BackupManagerService extends IBackupManager.Stub { Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer); (new PerformRestoreTask(params.transport, params.observer, params.token, params.pkgInfo, params.pmToken, params.needFullBackup)).run(); params.needFullBackup, params.filterSet)).run(); break; } Loading Loading @@ -3020,6 +3034,7 @@ class BackupManagerService extends IBackupManager.Stub { private File mStateDir; private int mPmToken; private boolean mNeedFullBackup; private HashSet<String> mFilterSet; class RestoreRequest { public PackageInfo app; Loading @@ -3033,7 +3048,7 @@ class BackupManagerService extends IBackupManager.Stub { PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer, long restoreSetToken, PackageInfo targetPackage, int pmToken, boolean needFullBackup) { boolean needFullBackup, String[] filterSet) { mTransport = transport; mObserver = observer; mToken = restoreSetToken; Loading @@ -3041,6 +3056,15 @@ class BackupManagerService extends IBackupManager.Stub { mPmToken = pmToken; mNeedFullBackup = needFullBackup; if (filterSet != null) { mFilterSet = new HashSet<String>(); for (String pkg : filterSet) { mFilterSet.add(pkg); } } else { mFilterSet = null; } try { mStateDir = new File(mBaseStateDir, transport.transportDirName()); } catch (RemoteException e) { Loading @@ -3052,7 +3076,8 @@ class BackupManagerService extends IBackupManager.Stub { long startRealtime = SystemClock.elapsedRealtime(); if (DEBUG) Slog.v(TAG, "Beginning restore process mTransport=" + mTransport + " mObserver=" + mObserver + " mToken=" + Long.toHexString(mToken) + " mTargetPackage=" + mTargetPackage + " mPmToken=" + mPmToken); + " mTargetPackage=" + mTargetPackage + " mFilterSet=" + mFilterSet + " mPmToken=" + mPmToken); PackageManagerBackupAgent pmAgent = null; int error = -1; // assume error Loading @@ -3071,6 +3096,22 @@ class BackupManagerService extends IBackupManager.Stub { List<PackageInfo> agentPackages = allAgentPackages(); if (mTargetPackage == null) { // if there's a filter set, strip out anything that isn't // present before proceeding if (mFilterSet != null) { for (int i = agentPackages.size() - 1; i >= 0; i--) { final PackageInfo pkg = agentPackages.get(i); if (! mFilterSet.contains(pkg.packageName)) { agentPackages.remove(i); } } if (DEBUG) { Slog.i(TAG, "Post-filter package set for restore:"); for (PackageInfo p : agentPackages) { Slog.i(TAG, " " + p); } } } restorePackages.addAll(agentPackages); } else { // Just one package to attempt restore of Loading Loading @@ -4266,6 +4307,67 @@ class BackupManagerService extends IBackupManager.Stub { return -1; } public synchronized int restoreSome(long token, IRestoreObserver observer, String[] packages) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "performRestore"); if (DEBUG) { StringBuilder b = new StringBuilder(128); b.append("restoreSome token="); b.append(Long.toHexString(token)); b.append(" observer="); b.append(observer.toString()); b.append(" packages="); if (packages == null) { b.append("null"); } else { b.append('{'); boolean first = true; for (String s : packages) { if (!first) { b.append(", "); } else first = false; b.append(s); } b.append('}'); } Slog.d(TAG, b.toString()); } if (mEnded) { throw new IllegalStateException("Restore session already ended"); } if (mRestoreTransport == null || mRestoreSets == null) { Slog.e(TAG, "Ignoring restoreAll() with no restore set"); return -1; } if (mPackageName != null) { Slog.e(TAG, "Ignoring restoreAll() on single-package session"); return -1; } synchronized (mQueueLock) { for (int i = 0; i < mRestoreSets.length; i++) { if (token == mRestoreSets[i].token) { long oldId = Binder.clearCallingIdentity(); mWakelock.acquire(); Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); msg.obj = new RestoreParams(mRestoreTransport, observer, token, packages, true); mBackupHandler.sendMessage(msg); Binder.restoreCallingIdentity(oldId); return 0; } } } Slog.w(TAG, "Restore token " + Long.toHexString(token) + " not found"); return -1; } public synchronized int restorePackage(String packageName, IRestoreObserver observer) { if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer); Loading