Loading cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +1 −1 Original line number Diff line number Diff line Loading @@ -315,7 +315,7 @@ public final class Bmgr { for (RestoreSet s : sets) { if (s.token == token) { System.out.println("Scheduling restore: " + s.name); didRestore = (mRestore.performRestore(token, observer) == 0); didRestore = (mRestore.restoreAll(token, observer) == 0); break; } } Loading core/java/android/backup/IRestoreSession.aidl +20 −1 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ interface IRestoreSession { * Restore the given set onto the device, replacing the current data of any app * contained in the restore 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 Loading @@ -47,7 +49,24 @@ interface IRestoreSession { * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. */ int performRestore(long token, IRestoreObserver observer); int restoreAll(long token, IRestoreObserver observer); /** * 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 * the dataset used during the last full device setup operation if the current * backup dataset has no matching data. If no backup data exists for this package * in either source, a nonzero value will be returned. * * @return Zero on success; nonzero on error. The observer will only receive * progress callbacks if this method returned zero. * @param packageName The name of the package whose data to restore. If this is * not the name of the caller's own package, then the android.permission.BACKUP * permission must be held. * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. */ int restorePackage(in String packageName, IRestoreObserver observer); /** * End this restore session. After this method is called, the IRestoreSession binder Loading core/java/android/backup/RestoreSession.java +40 −9 Original line number Diff line number Diff line Loading @@ -58,25 +58,56 @@ public class RestoreSession { * Restore the given set onto the device, replacing the current data of any app * contained in the restore 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 * @param token The token from {@link getAvailableRestoreSets()} corresponding to * the restore set that should be used. * @param observer If non-null, this argument points to an object that will receive * progress callbacks during the restore operation. These callbacks will occur * on the main thread of the application. * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. */ public int restoreAll(long token, RestoreObserver observer) { int err = -1; if (mObserver != null) { Log.d(TAG, "restoreAll() called during active restore"); return -1; } mObserver = new RestoreObserverWrapper(mContext, observer); try { err = mBinder.restoreAll(token, mObserver); } catch (RemoteException e) { Log.d(TAG, "Can't contact server to restore"); } 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 * the dataset used during the last full device setup operation if the current * backup dataset has no matching data. If no backup data exists for this package * in either source, a nonzero value will be returned. * * @return Zero on success; nonzero on error. The observer will only receive * progress callbacks if this method returned zero. * @param packageName The name of the package whose data to restore. If this is * not the name of the caller's own package, then the android.permission.BACKUP * permission must be held. * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. */ public int performRestore(long token, RestoreObserver observer) { public int restorePackage(String packageName, RestoreObserver observer) { int err = -1; if (mObserver != null) { Log.d(TAG, "performRestore() called during active restore"); Log.d(TAG, "restorePackage() called during active restore"); return -1; } mObserver = new RestoreObserverWrapper(mContext, observer); try { err = mBinder.performRestore(token, mObserver); err = mBinder.restorePackage(packageName, mObserver); } catch (RemoteException e) { Log.d(TAG, "Can't contact server to perform restore"); Log.d(TAG, "Can't contact server to restore package"); } return err; } Loading @@ -87,7 +118,7 @@ public class RestoreSession { * * <p><b>Note:</b> The caller <i>must</i> invoke this method to end the restore session, * even if {@link #getAvailableRestoreSets()} or * {@link #performRestore(long, RestoreObserver)} failed. * {@link #restorePackage(long, String, RestoreObserver)} failed. */ public void endRestoreSession() { try { Loading services/java/com/android/server/BackupManagerService.java +123 −9 Original line number Diff line number Diff line Loading @@ -176,11 +176,21 @@ class BackupManagerService extends IBackupManager.Stub { public IBackupTransport transport; public IRestoreObserver observer; public long token; public PackageInfo pkgInfo; RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, PackageInfo _pkg) { transport = _transport; observer = _obs; token = _token; pkgInfo = _pkg; } RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token) { transport = _transport; observer = _obs; token = _token; pkgInfo = null; } } Loading Loading @@ -210,10 +220,16 @@ class BackupManagerService extends IBackupManager.Stub { File mJournalDir; File mJournal; // Keep a log of all the apps we've ever backed up // Keep a log of all the apps we've ever backed up, and what the // dataset tokens are for both the current backup dataset and // the ancestral dataset. private File mEverStored; HashSet<String> mEverStoredApps = new HashSet<String>(); File mTokenFile; long mAncestralToken = 0; long mCurrentToken = 0; // Persistently track the need to do a full init static final String INIT_SENTINEL_FILE_NAME = "_need_init_"; HashSet<String> mPendingInits = new HashSet<String>(); // transport names Loading Loading @@ -277,7 +293,7 @@ class BackupManagerService extends IBackupManager.Stub { RestoreParams params = (RestoreParams)msg.obj; Log.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer); (new PerformRestoreTask(params.transport, params.observer, params.token)).run(); params.token, params.pkgInfo)).run(); break; } Loading Loading @@ -475,6 +491,16 @@ class BackupManagerService extends IBackupManager.Stub { private void initPackageTracking() { if (DEBUG) Log.v(TAG, "Initializing package tracking"); // Remember our ancestral dataset mTokenFile = new File(mBaseStateDir, "ancestral"); try { RandomAccessFile tf = new RandomAccessFile(mTokenFile, "r"); mAncestralToken = tf.readLong(); mCurrentToken = tf.readLong(); } catch (IOException e) { Log.w(TAG, "Unable to read token file", e); } // Keep a log of what apps we've ever backed up. Because we might have // rebooted in the middle of an operation that was removing something from // this log, we sanity-check its contents here and reconstruct it. Loading Loading @@ -607,6 +633,9 @@ class BackupManagerService extends IBackupManager.Stub { mEverStoredApps.clear(); mEverStored.delete(); mCurrentToken = 0; writeRestoreTokens(); // Remove all the state files for (File sf : stateFileDir.listFiles()) { // ... but don't touch the needs-init sentinel Loading Loading @@ -880,7 +909,7 @@ class BackupManagerService extends IBackupManager.Stub { addPackageParticipantsLockedInner(packageName, allApps); } // Called from the backup thread: record that the given app has been successfully // Called from the backup task: record that the given app has been successfully // backed up at least once void logBackupComplete(String packageName) { if (packageName.equals(PACKAGE_MANAGER_SENTINEL)) return; Loading Loading @@ -938,6 +967,18 @@ class BackupManagerService extends IBackupManager.Stub { } } // Record the current and ancestral backup tokens persistently void writeRestoreTokens() { try { RandomAccessFile af = new RandomAccessFile(mTokenFile, "rwd"); af.writeLong(mAncestralToken); af.writeLong(mCurrentToken); af.close(); } catch (IOException e) { Log.w(TAG, "Unable to write token file:", e); } } // Return the given transport private IBackupTransport getTransport(String transportName) { synchronized (mTransports) { Loading Loading @@ -1154,6 +1195,16 @@ class BackupManagerService extends IBackupManager.Stub { Log.e(TAG, "Error in backup thread", e); status = BackupConstants.TRANSPORT_ERROR; } finally { // If everything actually went through and this is the first time we've // done a backup, we can now record what the current backup dataset token // is. if ((mCurrentToken == 0) && (status != BackupConstants.TRANSPORT_OK)) { try { mCurrentToken = mTransport.getCurrentRestoreSet(); } catch (RemoteException e) { /* cannot happen */ } writeRestoreTokens(); } // If things went wrong, we need to re-stage the apps we had expected // to be backing up in this pass. This journals the package names in // the current active pending-backup file, not in the we are holding Loading Loading @@ -1395,6 +1446,7 @@ class BackupManagerService extends IBackupManager.Stub { private IBackupTransport mTransport; private IRestoreObserver mObserver; private long mToken; private PackageInfo mTargetPackage; private File mStateDir; class RestoreRequest { Loading @@ -1408,11 +1460,11 @@ class BackupManagerService extends IBackupManager.Stub { } PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer, long restoreSetToken) { long restoreSetToken, PackageInfo targetPackage) { mTransport = transport; Log.d(TAG, "PerformRestoreThread mObserver=" + mObserver); mObserver = observer; mToken = restoreSetToken; mTargetPackage = targetPackage; try { mStateDir = new File(mBaseStateDir, transport.transportDirName()); Loading @@ -1424,7 +1476,8 @@ class BackupManagerService extends IBackupManager.Stub { public void run() { long startRealtime = SystemClock.elapsedRealtime(); if (DEBUG) Log.v(TAG, "Beginning restore process mTransport=" + mTransport + " mObserver=" + mObserver + " mToken=" + Long.toHexString(mToken)); + " mObserver=" + mObserver + " mToken=" + Long.toHexString(mToken) + " mTargetPackage=" + mTargetPackage); /** * Restore sequence: * Loading @@ -1441,7 +1494,7 @@ class BackupManagerService extends IBackupManager.Stub { * * On errors, we try our best to recover and move on to the next * application, but if necessary we abort the whole operation -- * the user is waiting, after al. * the user is waiting, after all. */ int error = -1; // assume error Loading @@ -1459,7 +1512,12 @@ class BackupManagerService extends IBackupManager.Stub { restorePackages.add(omPackage); List<PackageInfo> agentPackages = allAgentPackages(); if (mTargetPackage == null) { restorePackages.addAll(agentPackages); } else { // Just one package to attempt restore of restorePackages.add(mTargetPackage); } // let the observer know that we're running if (mObserver != null) { Loading Loading @@ -1641,6 +1699,13 @@ class BackupManagerService extends IBackupManager.Stub { } } // If this was a restoreAll operation, record that this was our // ancestral dataset if (mTargetPackage == null) { mAncestralToken = mToken; writeRestoreTokens(); } // done; we can finally release the wakelock mWakelock.release(); } Loading Loading @@ -2219,7 +2284,7 @@ class BackupManagerService extends IBackupManager.Stub { } } public synchronized int performRestore(long token, IRestoreObserver observer) { public synchronized int restoreAll(long token, IRestoreObserver observer) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "performRestore"); Loading Loading @@ -2249,6 +2314,55 @@ class BackupManagerService extends IBackupManager.Stub { return -1; } public synchronized int restorePackage(String packageName, IRestoreObserver observer) { if (DEBUG) Log.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer); PackageInfo app = null; try { app = mPackageManager.getPackageInfo(packageName, 0); } catch (NameNotFoundException nnf) { Log.w(TAG, "Asked to restore nonexistent pkg " + packageName); return -1; } // If the caller is not privileged and is not coming from the target // app's uid, throw a permission exception back to the caller. int perm = mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(), Binder.getCallingUid()); if ((perm == PackageManager.PERMISSION_DENIED) && (app.applicationInfo.uid != Binder.getCallingUid())) { Log.w(TAG, "restorePackage: bad packageName=" + packageName + " or calling uid=" + Binder.getCallingUid()); throw new SecurityException("No permission to restore other packages"); } // So far so good; we're allowed to try to restore this package. Now // check whether there is data for it in the current dataset, falling back // to the ancestral dataset if not. long token = mAncestralToken; synchronized (mQueueLock) { if (mEverStoredApps.contains(packageName)) { token = mCurrentToken; } } // If we didn't come up with a place to look -- no ancestral dataset and // the app has never been backed up from this device -- there's nothing // to do but return failure. if (token == 0) { return -1; } // Ready to go: enqueue the restore request and claim success long oldId = Binder.clearCallingIdentity(); mWakelock.acquire(); Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); msg.obj = new RestoreParams(mRestoreTransport, observer, token, app); mBackupHandler.sendMessage(msg); Binder.restoreCallingIdentity(oldId); return 0; } public synchronized void endRestoreSession() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "endRestoreSession"); Loading Loading
cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java +1 −1 Original line number Diff line number Diff line Loading @@ -315,7 +315,7 @@ public final class Bmgr { for (RestoreSet s : sets) { if (s.token == token) { System.out.println("Scheduling restore: " + s.name); didRestore = (mRestore.performRestore(token, observer) == 0); didRestore = (mRestore.restoreAll(token, observer) == 0); break; } } Loading
core/java/android/backup/IRestoreSession.aidl +20 −1 Original line number Diff line number Diff line Loading @@ -40,6 +40,8 @@ interface IRestoreSession { * Restore the given set onto the device, replacing the current data of any app * contained in the restore 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 Loading @@ -47,7 +49,24 @@ interface IRestoreSession { * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. */ int performRestore(long token, IRestoreObserver observer); int restoreAll(long token, IRestoreObserver observer); /** * 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 * the dataset used during the last full device setup operation if the current * backup dataset has no matching data. If no backup data exists for this package * in either source, a nonzero value will be returned. * * @return Zero on success; nonzero on error. The observer will only receive * progress callbacks if this method returned zero. * @param packageName The name of the package whose data to restore. If this is * not the name of the caller's own package, then the android.permission.BACKUP * permission must be held. * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. */ int restorePackage(in String packageName, IRestoreObserver observer); /** * End this restore session. After this method is called, the IRestoreSession binder Loading
core/java/android/backup/RestoreSession.java +40 −9 Original line number Diff line number Diff line Loading @@ -58,25 +58,56 @@ public class RestoreSession { * Restore the given set onto the device, replacing the current data of any app * contained in the restore 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 * @param token The token from {@link getAvailableRestoreSets()} corresponding to * the restore set that should be used. * @param observer If non-null, this argument points to an object that will receive * progress callbacks during the restore operation. These callbacks will occur * on the main thread of the application. * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. */ public int restoreAll(long token, RestoreObserver observer) { int err = -1; if (mObserver != null) { Log.d(TAG, "restoreAll() called during active restore"); return -1; } mObserver = new RestoreObserverWrapper(mContext, observer); try { err = mBinder.restoreAll(token, mObserver); } catch (RemoteException e) { Log.d(TAG, "Can't contact server to restore"); } 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 * the dataset used during the last full device setup operation if the current * backup dataset has no matching data. If no backup data exists for this package * in either source, a nonzero value will be returned. * * @return Zero on success; nonzero on error. The observer will only receive * progress callbacks if this method returned zero. * @param packageName The name of the package whose data to restore. If this is * not the name of the caller's own package, then the android.permission.BACKUP * permission must be held. * @param observer If non-null, this binder points to an object that will receive * progress callbacks during the restore operation. */ public int performRestore(long token, RestoreObserver observer) { public int restorePackage(String packageName, RestoreObserver observer) { int err = -1; if (mObserver != null) { Log.d(TAG, "performRestore() called during active restore"); Log.d(TAG, "restorePackage() called during active restore"); return -1; } mObserver = new RestoreObserverWrapper(mContext, observer); try { err = mBinder.performRestore(token, mObserver); err = mBinder.restorePackage(packageName, mObserver); } catch (RemoteException e) { Log.d(TAG, "Can't contact server to perform restore"); Log.d(TAG, "Can't contact server to restore package"); } return err; } Loading @@ -87,7 +118,7 @@ public class RestoreSession { * * <p><b>Note:</b> The caller <i>must</i> invoke this method to end the restore session, * even if {@link #getAvailableRestoreSets()} or * {@link #performRestore(long, RestoreObserver)} failed. * {@link #restorePackage(long, String, RestoreObserver)} failed. */ public void endRestoreSession() { try { Loading
services/java/com/android/server/BackupManagerService.java +123 −9 Original line number Diff line number Diff line Loading @@ -176,11 +176,21 @@ class BackupManagerService extends IBackupManager.Stub { public IBackupTransport transport; public IRestoreObserver observer; public long token; public PackageInfo pkgInfo; RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token, PackageInfo _pkg) { transport = _transport; observer = _obs; token = _token; pkgInfo = _pkg; } RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token) { transport = _transport; observer = _obs; token = _token; pkgInfo = null; } } Loading Loading @@ -210,10 +220,16 @@ class BackupManagerService extends IBackupManager.Stub { File mJournalDir; File mJournal; // Keep a log of all the apps we've ever backed up // Keep a log of all the apps we've ever backed up, and what the // dataset tokens are for both the current backup dataset and // the ancestral dataset. private File mEverStored; HashSet<String> mEverStoredApps = new HashSet<String>(); File mTokenFile; long mAncestralToken = 0; long mCurrentToken = 0; // Persistently track the need to do a full init static final String INIT_SENTINEL_FILE_NAME = "_need_init_"; HashSet<String> mPendingInits = new HashSet<String>(); // transport names Loading Loading @@ -277,7 +293,7 @@ class BackupManagerService extends IBackupManager.Stub { RestoreParams params = (RestoreParams)msg.obj; Log.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer); (new PerformRestoreTask(params.transport, params.observer, params.token)).run(); params.token, params.pkgInfo)).run(); break; } Loading Loading @@ -475,6 +491,16 @@ class BackupManagerService extends IBackupManager.Stub { private void initPackageTracking() { if (DEBUG) Log.v(TAG, "Initializing package tracking"); // Remember our ancestral dataset mTokenFile = new File(mBaseStateDir, "ancestral"); try { RandomAccessFile tf = new RandomAccessFile(mTokenFile, "r"); mAncestralToken = tf.readLong(); mCurrentToken = tf.readLong(); } catch (IOException e) { Log.w(TAG, "Unable to read token file", e); } // Keep a log of what apps we've ever backed up. Because we might have // rebooted in the middle of an operation that was removing something from // this log, we sanity-check its contents here and reconstruct it. Loading Loading @@ -607,6 +633,9 @@ class BackupManagerService extends IBackupManager.Stub { mEverStoredApps.clear(); mEverStored.delete(); mCurrentToken = 0; writeRestoreTokens(); // Remove all the state files for (File sf : stateFileDir.listFiles()) { // ... but don't touch the needs-init sentinel Loading Loading @@ -880,7 +909,7 @@ class BackupManagerService extends IBackupManager.Stub { addPackageParticipantsLockedInner(packageName, allApps); } // Called from the backup thread: record that the given app has been successfully // Called from the backup task: record that the given app has been successfully // backed up at least once void logBackupComplete(String packageName) { if (packageName.equals(PACKAGE_MANAGER_SENTINEL)) return; Loading Loading @@ -938,6 +967,18 @@ class BackupManagerService extends IBackupManager.Stub { } } // Record the current and ancestral backup tokens persistently void writeRestoreTokens() { try { RandomAccessFile af = new RandomAccessFile(mTokenFile, "rwd"); af.writeLong(mAncestralToken); af.writeLong(mCurrentToken); af.close(); } catch (IOException e) { Log.w(TAG, "Unable to write token file:", e); } } // Return the given transport private IBackupTransport getTransport(String transportName) { synchronized (mTransports) { Loading Loading @@ -1154,6 +1195,16 @@ class BackupManagerService extends IBackupManager.Stub { Log.e(TAG, "Error in backup thread", e); status = BackupConstants.TRANSPORT_ERROR; } finally { // If everything actually went through and this is the first time we've // done a backup, we can now record what the current backup dataset token // is. if ((mCurrentToken == 0) && (status != BackupConstants.TRANSPORT_OK)) { try { mCurrentToken = mTransport.getCurrentRestoreSet(); } catch (RemoteException e) { /* cannot happen */ } writeRestoreTokens(); } // If things went wrong, we need to re-stage the apps we had expected // to be backing up in this pass. This journals the package names in // the current active pending-backup file, not in the we are holding Loading Loading @@ -1395,6 +1446,7 @@ class BackupManagerService extends IBackupManager.Stub { private IBackupTransport mTransport; private IRestoreObserver mObserver; private long mToken; private PackageInfo mTargetPackage; private File mStateDir; class RestoreRequest { Loading @@ -1408,11 +1460,11 @@ class BackupManagerService extends IBackupManager.Stub { } PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer, long restoreSetToken) { long restoreSetToken, PackageInfo targetPackage) { mTransport = transport; Log.d(TAG, "PerformRestoreThread mObserver=" + mObserver); mObserver = observer; mToken = restoreSetToken; mTargetPackage = targetPackage; try { mStateDir = new File(mBaseStateDir, transport.transportDirName()); Loading @@ -1424,7 +1476,8 @@ class BackupManagerService extends IBackupManager.Stub { public void run() { long startRealtime = SystemClock.elapsedRealtime(); if (DEBUG) Log.v(TAG, "Beginning restore process mTransport=" + mTransport + " mObserver=" + mObserver + " mToken=" + Long.toHexString(mToken)); + " mObserver=" + mObserver + " mToken=" + Long.toHexString(mToken) + " mTargetPackage=" + mTargetPackage); /** * Restore sequence: * Loading @@ -1441,7 +1494,7 @@ class BackupManagerService extends IBackupManager.Stub { * * On errors, we try our best to recover and move on to the next * application, but if necessary we abort the whole operation -- * the user is waiting, after al. * the user is waiting, after all. */ int error = -1; // assume error Loading @@ -1459,7 +1512,12 @@ class BackupManagerService extends IBackupManager.Stub { restorePackages.add(omPackage); List<PackageInfo> agentPackages = allAgentPackages(); if (mTargetPackage == null) { restorePackages.addAll(agentPackages); } else { // Just one package to attempt restore of restorePackages.add(mTargetPackage); } // let the observer know that we're running if (mObserver != null) { Loading Loading @@ -1641,6 +1699,13 @@ class BackupManagerService extends IBackupManager.Stub { } } // If this was a restoreAll operation, record that this was our // ancestral dataset if (mTargetPackage == null) { mAncestralToken = mToken; writeRestoreTokens(); } // done; we can finally release the wakelock mWakelock.release(); } Loading Loading @@ -2219,7 +2284,7 @@ class BackupManagerService extends IBackupManager.Stub { } } public synchronized int performRestore(long token, IRestoreObserver observer) { public synchronized int restoreAll(long token, IRestoreObserver observer) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "performRestore"); Loading Loading @@ -2249,6 +2314,55 @@ class BackupManagerService extends IBackupManager.Stub { return -1; } public synchronized int restorePackage(String packageName, IRestoreObserver observer) { if (DEBUG) Log.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer); PackageInfo app = null; try { app = mPackageManager.getPackageInfo(packageName, 0); } catch (NameNotFoundException nnf) { Log.w(TAG, "Asked to restore nonexistent pkg " + packageName); return -1; } // If the caller is not privileged and is not coming from the target // app's uid, throw a permission exception back to the caller. int perm = mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(), Binder.getCallingUid()); if ((perm == PackageManager.PERMISSION_DENIED) && (app.applicationInfo.uid != Binder.getCallingUid())) { Log.w(TAG, "restorePackage: bad packageName=" + packageName + " or calling uid=" + Binder.getCallingUid()); throw new SecurityException("No permission to restore other packages"); } // So far so good; we're allowed to try to restore this package. Now // check whether there is data for it in the current dataset, falling back // to the ancestral dataset if not. long token = mAncestralToken; synchronized (mQueueLock) { if (mEverStoredApps.contains(packageName)) { token = mCurrentToken; } } // If we didn't come up with a place to look -- no ancestral dataset and // the app has never been backed up from this device -- there's nothing // to do but return failure. if (token == 0) { return -1; } // Ready to go: enqueue the restore request and claim success long oldId = Binder.clearCallingIdentity(); mWakelock.acquire(); Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); msg.obj = new RestoreParams(mRestoreTransport, observer, token, app); mBackupHandler.sendMessage(msg); Binder.restoreCallingIdentity(oldId); return 0; } public synchronized void endRestoreSession() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "endRestoreSession"); Loading