diff options
Diffstat (limited to 'services/java/com/android/server/BackupManagerService.java')
| -rw-r--r-- | services/java/com/android/server/BackupManagerService.java | 516 |
1 files changed, 265 insertions, 251 deletions
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 197404e..bbebba3 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -47,6 +47,7 @@ import android.util.Log; import android.util.SparseArray; import android.backup.IBackupManager; +import android.backup.IRestoreObserver; import android.backup.IRestoreSession; import android.backup.BackupManager; import android.backup.RestoreSet; @@ -76,12 +77,12 @@ class BackupManagerService extends IBackupManager.Stub { private static final boolean DEBUG = true; // Default time to wait after data changes before we back up the data - private static final long COLLECTION_INTERVAL = 1000; - //private static final long COLLECTION_INTERVAL = 3 * 60 * 1000; + private static final long COLLECTION_INTERVAL = 3 * 60 * 1000; private static final int MSG_RUN_BACKUP = 1; private static final int MSG_RUN_FULL_BACKUP = 2; private static final int MSG_RUN_RESTORE = 3; + private static final String RESTORE_OBSERVER_KEY = "_resOb"; // Timeout interval for deciding that a bind or clear-data has taken too long static final long TIMEOUT_INTERVAL = 10 * 1000; @@ -110,8 +111,8 @@ class BackupManagerService extends IBackupManager.Stub { // Backups that we haven't started yet. private HashMap<ApplicationInfo,BackupRequest> mPendingBackups = new HashMap<ApplicationInfo,BackupRequest>(); - // Do we need to back up the package manager metadata on the next pass? - private boolean mDoPackageManager; + + // Pseudoname that we use for the Package Manager metadata "package" private static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; // locking around the pending-backup management @@ -134,7 +135,20 @@ class BackupManagerService extends IBackupManager.Stub { private IBackupTransport mLocalTransport, mGoogleTransport; private RestoreSession mActiveRestoreSession; - private File mStateDir; + private class RestoreParams { + public IBackupTransport transport; + public IRestoreObserver observer; + public long token; + + RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token) { + transport = _transport; + observer = _obs; + token = _token; + } + } + + // Where we keep our journal files and other bookkeeping + private File mBaseStateDir; private File mDataDir; private File mJournalDir; private File mJournal; @@ -146,13 +160,12 @@ class BackupManagerService extends IBackupManager.Stub { mActivityManager = ActivityManagerNative.getDefault(); // Set up our bookkeeping - mStateDir = new File(Environment.getDataDirectory(), "backup"); - mStateDir.mkdirs(); + mBaseStateDir = new File(Environment.getDataDirectory(), "backup"); mDataDir = Environment.getDownloadCacheDirectory(); // Set up the backup-request journaling - mJournalDir = new File(mStateDir, "pending"); - mJournalDir.mkdirs(); + mJournalDir = new File(mBaseStateDir, "pending"); + mJournalDir.mkdirs(); // creates mBaseStateDir along the way makeJournalLocked(); // okay because no other threads are running yet // Build our mapping of uid to backup client services. This implicitly @@ -165,8 +178,7 @@ class BackupManagerService extends IBackupManager.Stub { // Set up our transport options and initialize the default transport // TODO: Have transports register themselves somehow? // TODO: Don't create transports that we don't need to? - mTransportId = BackupManager.TRANSPORT_LOCAL; - //mTransportId = BackupManager.TRANSPORT_GOOGLE; + mTransportId = BackupManager.TRANSPORT_GOOGLE; mLocalTransport = new LocalTransport(context); // This is actually pretty cheap mGoogleTransport = null; @@ -337,9 +349,8 @@ class BackupManagerService extends IBackupManager.Stub { case MSG_RUN_RESTORE: { - int token = msg.arg1; - IBackupTransport transport = (IBackupTransport)msg.obj; - (new PerformRestoreThread(transport, token)).start(); + RestoreParams params = (RestoreParams)msg.obj; + (new PerformRestoreThread(params.transport, params.observer, params.token)).start(); break; } } @@ -351,29 +362,29 @@ class BackupManagerService extends IBackupManager.Stub { void addPackageParticipantsLocked(String packageName) { // Look for apps that define the android:backupAgent attribute if (DEBUG) Log.v(TAG, "addPackageParticipantsLocked: " + packageName); - List<ApplicationInfo> targetApps = allAgentApps(); + List<PackageInfo> targetApps = allAgentPackages(); addPackageParticipantsLockedInner(packageName, targetApps); } private void addPackageParticipantsLockedInner(String packageName, - List<ApplicationInfo> targetApps) { + List<PackageInfo> targetPkgs) { if (DEBUG) { - Log.v(TAG, "Adding " + targetApps.size() + " backup participants:"); - for (ApplicationInfo a : targetApps) { - Log.v(TAG, " " + a + " agent=" + a.backupAgentName); + Log.v(TAG, "Adding " + targetPkgs.size() + " backup participants:"); + for (PackageInfo p : targetPkgs) { + Log.v(TAG, " " + p + " agent=" + p.applicationInfo.backupAgentName + + " uid=" + p.applicationInfo.uid); } } - for (ApplicationInfo app : targetApps) { - if (packageName == null || app.packageName.equals(packageName)) { - int uid = app.uid; + for (PackageInfo pkg : targetPkgs) { + if (packageName == null || pkg.packageName.equals(packageName)) { + int uid = pkg.applicationInfo.uid; HashSet<ApplicationInfo> set = mBackupParticipants.get(uid); if (set == null) { set = new HashSet<ApplicationInfo>(); mBackupParticipants.put(uid, set); } - set.add(app); - backUpPackageManagerData(); + set.add(pkg.applicationInfo); } } } @@ -382,67 +393,66 @@ class BackupManagerService extends IBackupManager.Stub { // 'packageName' is null, *all* participating apps will be removed. void removePackageParticipantsLocked(String packageName) { if (DEBUG) Log.v(TAG, "removePackageParticipantsLocked: " + packageName); - List<ApplicationInfo> allApps = null; + List<PackageInfo> allApps = null; if (packageName != null) { - allApps = new ArrayList<ApplicationInfo>(); + allApps = new ArrayList<PackageInfo>(); try { - ApplicationInfo app = mPackageManager.getApplicationInfo(packageName, 0); - allApps.add(app); + int flags = PackageManager.GET_SIGNATURES; + allApps.add(mPackageManager.getPackageInfo(packageName, flags)); } catch (Exception e) { - // just skip it + // just skip it (???) } } else { // all apps with agents - allApps = allAgentApps(); + allApps = allAgentPackages(); } removePackageParticipantsLockedInner(packageName, allApps); } private void removePackageParticipantsLockedInner(String packageName, - List<ApplicationInfo> agents) { + List<PackageInfo> agents) { if (DEBUG) { Log.v(TAG, "removePackageParticipantsLockedInner (" + packageName + ") removing " + agents.size() + " entries"); - for (ApplicationInfo a : agents) { - Log.v(TAG, " - " + a); + for (PackageInfo p : agents) { + Log.v(TAG, " - " + p); } } - for (ApplicationInfo app : agents) { - if (packageName == null || app.packageName.equals(packageName)) { - int uid = app.uid; + for (PackageInfo pkg : agents) { + if (packageName == null || pkg.packageName.equals(packageName)) { + int uid = pkg.applicationInfo.uid; HashSet<ApplicationInfo> set = mBackupParticipants.get(uid); if (set != null) { // Find the existing entry with the same package name, and remove it. // We can't just remove(app) because the instances are different. for (ApplicationInfo entry: set) { - if (entry.packageName.equals(app.packageName)) { + if (entry.packageName.equals(pkg.packageName)) { set.remove(entry); - backUpPackageManagerData(); break; } } if (set.size() == 0) { - mBackupParticipants.delete(uid); } + mBackupParticipants.delete(uid); + } } } } } // Returns the set of all applications that define an android:backupAgent attribute - private List<ApplicationInfo> allAgentApps() { + private List<PackageInfo> allAgentPackages() { // !!! TODO: cache this and regenerate only when necessary - List<ApplicationInfo> allApps = mPackageManager.getInstalledApplications(0); - int N = allApps.size(); - if (N > 0) { - for (int a = N-1; a >= 0; a--) { - ApplicationInfo app = allApps.get(a); - if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) - || app.backupAgentName == null) { - allApps.remove(a); - } + int flags = PackageManager.GET_SIGNATURES; + List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags); + int N = packages.size(); + for (int a = N-1; a >= 0; a--) { + ApplicationInfo app = packages.get(a).applicationInfo; + if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) + || app.backupAgentName == null) { + packages.remove(a); } } - return allApps; + return packages; } // Reset the given package's known backup participants. Unlike add/remove, the update @@ -455,19 +465,11 @@ class BackupManagerService extends IBackupManager.Stub { if (DEBUG) Log.v(TAG, "updatePackageParticipantsLocked: " + packageName); // brute force but small code size - List<ApplicationInfo> allApps = allAgentApps(); + List<PackageInfo> allApps = allAgentPackages(); removePackageParticipantsLockedInner(packageName, allApps); addPackageParticipantsLockedInner(packageName, allApps); } - private void backUpPackageManagerData() { - // No need to schedule a backup just for the metadata; just piggyback on - // the next actual data backup. - synchronized(this) { - mDoPackageManager = true; - } - } - // The queue lock should be held when scheduling a backup pass private void scheduleBackupPassLocked(long timeFromNowMillis) { mBackupHandler.removeMessages(MSG_RUN_BACKUP); @@ -565,6 +567,7 @@ class BackupManagerService extends IBackupManager.Stub { private static final String TAG = "PerformBackupThread"; IBackupTransport mTransport; ArrayList<BackupRequest> mQueue; + File mStateDir; File mJournal; public PerformBackupThread(IBackupTransport transport, ArrayList<BackupRequest> queue, @@ -572,52 +575,43 @@ class BackupManagerService extends IBackupManager.Stub { mTransport = transport; mQueue = queue; mJournal = journal; + + try { + mStateDir = new File(mBaseStateDir, transport.transportDirName()); + } catch (RemoteException e) { + // can't happen; the transport is local + } + mStateDir.mkdirs(); } @Override public void run() { if (DEBUG) Log.v(TAG, "Beginning backup of " + mQueue.size() + " targets"); - // start up the transport - try { - mTransport.startSession(); - } catch (Exception e) { - Log.e(TAG, "Error session transport"); - e.printStackTrace(); - return; - } - - // The transport is up and running. First, back up the package manager - // metadata if necessary - boolean doPackageManager; - synchronized (BackupManagerService.this) { - doPackageManager = mDoPackageManager; - mDoPackageManager = false; - } - if (doPackageManager) { - // The package manager doesn't have a proper <application> etc, but since - // it's running here in the system process we can just set up its agent - // directly and use a synthetic BackupRequest. - if (DEBUG) Log.i(TAG, "Running PM backup pass as well"); - - PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent( - mPackageManager, allAgentApps()); - BackupRequest pmRequest = new BackupRequest(new ApplicationInfo(), false); - pmRequest.appInfo.packageName = PACKAGE_MANAGER_SENTINEL; - processOneBackup(pmRequest, - IBackupAgent.Stub.asInterface(pmAgent.onBind()), - mTransport); - } + // The package manager doesn't have a proper <application> etc, but since + // it's running here in the system process we can just set up its agent + // directly and use a synthetic BackupRequest. We always run this pass + // because it's cheap and this way we guarantee that we don't get out of + // step even if we're selecting among various transports at run time. + PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent( + mPackageManager, allAgentPackages()); + BackupRequest pmRequest = new BackupRequest(new ApplicationInfo(), false); + pmRequest.appInfo.packageName = PACKAGE_MANAGER_SENTINEL; + processOneBackup(pmRequest, + IBackupAgent.Stub.asInterface(pmAgent.onBind()), + mTransport); // Now run all the backups in our queue doQueuedBackups(mTransport); // Finally, tear down the transport try { - mTransport.endSession(); - } catch (Exception e) { - Log.e(TAG, "Error ending transport"); - e.printStackTrace(); + if (!mTransport.finishBackup()) { + // STOPSHIP TODO: handle errors + Log.e(TAG, "Backup failure in finishBackup()"); + } + } catch (RemoteException e) { + Log.e(TAG, "Error in finishBackup()", e); } if (!mJournal.delete()) { @@ -712,24 +706,18 @@ class BackupManagerService extends IBackupManager.Stub { if (DEBUG) Log.v(TAG, "doBackup() success; calling transport"); backupData = ParcelFileDescriptor.open(backupDataName, ParcelFileDescriptor.MODE_READ_ONLY); - int error = transport.performBackup(packInfo, backupData); + if (!transport.performBackup(packInfo, backupData)) { + // STOPSHIP TODO: handle errors + Log.e(TAG, "Backup failure in performBackup()"); + } // !!! TODO: After successful transport, delete the now-stale data // and juggle the files so that next time the new state is passed //backupDataName.delete(); newStateName.renameTo(savedStateName); } - } catch (NameNotFoundException e) { - Log.e(TAG, "Package not found on backup: " + packageName); - } catch (FileNotFoundException fnf) { - Log.w(TAG, "File not found on backup: "); - fnf.printStackTrace(); - } catch (RemoteException e) { - Log.d(TAG, "Remote target " + request.appInfo.packageName + " threw during backup:"); - e.printStackTrace(); } catch (Exception e) { - Log.w(TAG, "Final exception guard in backup: "); - e.printStackTrace(); + Log.e(TAG, "Error backing up " + packageName, e); } } } @@ -737,25 +725,6 @@ class BackupManagerService extends IBackupManager.Stub { // ----- Restore handling ----- - // Is the given package restorable on this device? Returns the on-device app's - // ApplicationInfo struct if it is; null if not. - // - // !!! TODO: also consider signatures - PackageInfo isRestorable(PackageInfo packageInfo) { - if (packageInfo.packageName != null) { - try { - PackageInfo app = mPackageManager.getPackageInfo(packageInfo.packageName, - PackageManager.GET_SIGNATURES); - if ((app.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0) { - return app; - } - } catch (Exception e) { - // doesn't exist on this device, or other error -- just ignore it. - } - } - return null; - } - private boolean signaturesMatch(Signature[] storedSigs, Signature[] deviceSigs) { // Allow unsigned apps, but not signed on one device and unsigned on the other // !!! TODO: is this the right policy? @@ -792,8 +761,10 @@ class BackupManagerService extends IBackupManager.Stub { class PerformRestoreThread extends Thread { private IBackupTransport mTransport; - private int mToken; + private IRestoreObserver mObserver; + private long mToken; private RestoreSet mImage; + private File mStateDir; class RestoreRequest { public PackageInfo app; @@ -805,9 +776,18 @@ class BackupManagerService extends IBackupManager.Stub { } } - PerformRestoreThread(IBackupTransport transport, int restoreSetToken) { + PerformRestoreThread(IBackupTransport transport, IRestoreObserver observer, + long restoreSetToken) { mTransport = transport; + mObserver = observer; mToken = restoreSetToken; + + try { + mStateDir = new File(mBaseStateDir, transport.transportDirName()); + } catch (RemoteException e) { + // can't happen; the transport is local + } + mStateDir.mkdirs(); } @Override @@ -816,130 +796,175 @@ class BackupManagerService extends IBackupManager.Stub { /** * Restore sequence: * - * 1. start up the transport session - * 2. get the restore set description for our identity - * 3. for each app in the restore set: + * 1. get the restore set description for our identity + * 2. for each app in the restore set: * 3.a. if it's restorable on this device, add it to the restore queue - * 4. for each app in the restore queue: - * 4.a. clear the app data - * 4.b. get the restore data for the app from the transport - * 4.c. launch the backup agent for the app - * 4.d. agent.doRestore() with the data from the server - * 4.e. unbind the agent [and kill the app?] - * 5. shut down the transport + * 3. for each app in the restore queue: + * 3.a. clear the app data + * 3.b. get the restore data for the app from the transport + * 3.c. launch the backup agent for the app + * 3.d. agent.doRestore() with the data from the server + * 3.e. unbind the agent [and kill the app?] + * 4. shut down the transport */ - int err = -1; + int error = -1; // assume error + + // build the set of apps to restore try { - err = mTransport.startSession(); - } catch (Exception e) { - Log.e(TAG, "Error starting transport for restore"); - e.printStackTrace(); - } + RestoreSet[] images = mTransport.getAvailableRestoreSets(); + if (images == null) { + // STOPSHIP TODO: Handle the failure somehow? + Log.e(TAG, "Error getting restore sets"); + return; + } - if (err == 0) { - // build the set of apps to restore - try { - RestoreSet[] images = mTransport.getAvailableRestoreSets(); - if (images.length > 0) { - // !!! TODO: pick out the set for this token - mImage = images[0]; - - // Pull the Package Manager metadata from the restore set first - PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent( - mPackageManager, allAgentApps()); - PackageInfo pmApp = new PackageInfo(); - pmApp.packageName = PACKAGE_MANAGER_SENTINEL; - // !!! TODO: version currently ignored when 'restoring' the PM metadata - processOneRestore(pmApp, 0, - IBackupAgent.Stub.asInterface(pmAgent.onBind())); - - // build the set of apps we will attempt to restore - PackageInfo[] packages = mTransport.getAppSet(mImage.token); - HashSet<RestoreRequest> appsToRestore = new HashSet<RestoreRequest>(); - for (PackageInfo pkg: packages) { - // get the real PackageManager idea of the package - PackageInfo app = isRestorable(pkg); - if (app != null) { - // Validate against the backed-up signature block, too - Metadata info = pmAgent.getRestoredMetadata(app.packageName); - if (info != null) { - if (app.versionCode >= info.versionCode) { - if (DEBUG) Log.v(TAG, "Restore version " - + info.versionCode - + " compatible with app version " - + app.versionCode); - if (signaturesMatch(info.signatures, app.signatures)) { - appsToRestore.add( - new RestoreRequest(app, info.versionCode)); - } else { - Log.w(TAG, "Sig mismatch restoring " - + app.packageName); - } - } else { - Log.i(TAG, "Restore set for " + app.packageName - + " is too new [" + info.versionCode - + "] for installed app version " - + app.versionCode); - } - } else { - Log.d(TAG, "Unable to get metadata for " - + app.packageName); - } - } - } + if (images.length == 0) { + Log.i(TAG, "No restore sets available"); + return; + } + + mImage = images[0]; + + // Get the list of all packages which have backup enabled. + // (Include the Package Manager metadata pseudo-package first.) + ArrayList<PackageInfo> restorePackages = new ArrayList<PackageInfo>(); + PackageInfo omPackage = new PackageInfo(); + omPackage.packageName = PACKAGE_MANAGER_SENTINEL; + restorePackages.add(omPackage); - // now run the restore queue - doQueuedRestores(appsToRestore); + List<PackageInfo> agentPackages = allAgentPackages(); + restorePackages.addAll(agentPackages); + + // let the observer know that we're running + if (mObserver != null) { + try { + // !!! TODO: get an actual count from the transport after + // its startRestore() runs? + mObserver.restoreStarting(restorePackages.size()); + } catch (RemoteException e) { + Log.d(TAG, "Restore observer died at restoreStarting"); + mObserver = null; } - } catch (RemoteException e) { - // can't happen; transports run locally } - // done; shut down the transport - try { - mTransport.endSession(); - } catch (Exception e) { - Log.e(TAG, "Error ending transport for restore"); - e.printStackTrace(); + if (!mTransport.startRestore(mToken, restorePackages.toArray(new PackageInfo[0]))) { + // STOPSHIP TODO: Handle the failure somehow? + Log.e(TAG, "Error starting restore operation"); + return; } - } - // even if the initial session startup failed, report that we're done here - } + String packageName = mTransport.nextRestorePackage(); + if (packageName == null) { + // STOPSHIP TODO: Handle the failure somehow? + Log.e(TAG, "Error getting first restore package"); + return; + } else if (packageName.equals("")) { + Log.i(TAG, "No restore data available"); + return; + } else if (!packageName.equals(PACKAGE_MANAGER_SENTINEL)) { + Log.e(TAG, "Expected restore data for \"" + PACKAGE_MANAGER_SENTINEL + + "\", found only \"" + packageName + "\""); + return; + } + + // Pull the Package Manager metadata from the restore set first + PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent( + mPackageManager, agentPackages); + processOneRestore(omPackage, 0, IBackupAgent.Stub.asInterface(pmAgent.onBind())); + + int count = 0; + for (;;) { + packageName = mTransport.nextRestorePackage(); + if (packageName == null) { + // STOPSHIP TODO: Handle the failure somehow? + Log.e(TAG, "Error getting next restore package"); + return; + } else if (packageName.equals("")) { + break; + } - // restore each app in the queue - void doQueuedRestores(HashSet<RestoreRequest> appsToRestore) { - for (RestoreRequest req : appsToRestore) { - PackageInfo app = req.app; - Log.d(TAG, "starting agent for restore of " + app); + if (mObserver != null) { + ++count; + try { + mObserver.onUpdate(count); + } catch (RemoteException e) { + Log.d(TAG, "Restore observer died in onUpdate"); + mObserver = null; + } + } - try { - // Remove the app's data first - clearApplicationDataSynchronous(app.packageName); + Metadata metaInfo = pmAgent.getRestoredMetadata(packageName); + if (metaInfo == null) { + Log.e(TAG, "Missing metadata for " + packageName); + continue; + } + + int flags = PackageManager.GET_SIGNATURES; + PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, flags); + if (metaInfo.versionCode > packageInfo.versionCode) { + Log.w(TAG, "Package " + packageName + + " restore version [" + metaInfo.versionCode + + "] is too new for installed version [" + + packageInfo.versionCode + "]"); + continue; + } + + if (!signaturesMatch(metaInfo.signatures, packageInfo.signatures)) { + Log.w(TAG, "Signature mismatch restoring " + packageName); + continue; + } + + if (DEBUG) Log.v(TAG, "Package " + packageName + + " restore version [" + metaInfo.versionCode + + "] is compatible with installed version [" + + packageInfo.versionCode + "]"); - // Now perform the restore into the clean app - IBackupAgent agent = bindToAgentSynchronous(app.applicationInfo, + // Now perform the actual restore + clearApplicationDataSynchronous(packageName); + IBackupAgent agent = bindToAgentSynchronous( + packageInfo.applicationInfo, IApplicationThread.BACKUP_MODE_RESTORE); - if (agent != null) { - processOneRestore(app, req.storedAppVersion, agent); + if (agent == null) { + Log.w(TAG, "Can't find backup agent for " + packageName); + continue; } - // unbind even on timeout, just in case - mActivityManager.unbindBackupAgent(app.applicationInfo); - } catch (SecurityException ex) { - // Try for the next one. - Log.d(TAG, "error in bind", ex); + try { + processOneRestore(packageInfo, metaInfo.versionCode, agent); + } finally { + // unbind even on timeout or failure, just in case + mActivityManager.unbindBackupAgent(packageInfo.applicationInfo); + } + } + + // if we get this far, report success to the observer + error = 0; + } catch (NameNotFoundException e) { + // STOPSHIP TODO: Handle the failure somehow? + Log.e(TAG, "Invalid paackage restoring data", e); + } catch (RemoteException e) { + // STOPSHIP TODO: Handle the failure somehow? + Log.e(TAG, "Error restoring data", e); + } finally { + try { + mTransport.finishRestore(); } catch (RemoteException e) { - // can't happen + Log.e(TAG, "Error finishing restore", e); } + if (mObserver != null) { + try { + mObserver.restoreFinished(error); + } catch (RemoteException e) { + Log.d(TAG, "Restore observer died at restoreFinished"); + } + } } } - // Do the guts of a restore of one application, derived from the 'mImage' - // restore set via the 'mTransport' transport. - void processOneRestore(PackageInfo app, int storedAppVersion, IBackupAgent agent) { + // Do the guts of a restore of one application, using mTransport.getRestoreData(). + void processOneRestore(PackageInfo app, int appVersionCode, IBackupAgent agent) { // !!! TODO: actually run the restore through mTransport final String packageName = app.packageName; @@ -954,11 +979,12 @@ class BackupManagerService extends IBackupManager.Stub { // Run the transport's restore pass // Run the target's backup pass - int err = -1; try { - err = mTransport.getRestoreData(mImage.token, app, backupData); - } catch (RemoteException e) { - // can't happen + if (!mTransport.getRestoreData(backupData)) { + // STOPSHIP TODO: Handle this error somehow? + Log.e(TAG, "Error getting restore data for " + packageName); + return; + } } finally { backupData.close(); } @@ -973,30 +999,18 @@ class BackupManagerService extends IBackupManager.Stub { backupData = ParcelFileDescriptor.open(backupDataName, ParcelFileDescriptor.MODE_READ_ONLY); - boolean success = false; try { - agent.doRestore(backupData, storedAppVersion, newState); - success = true; - } catch (Exception e) { - Log.e(TAG, "Restore failed for " + packageName); - e.printStackTrace(); + agent.doRestore(backupData, appVersionCode, newState); } finally { newState.close(); backupData.close(); } // if everything went okay, remember the recorded state now - if (success) { - File savedStateName = new File(mStateDir, packageName); - newStateName.renameTo(savedStateName); - } - } catch (FileNotFoundException fnfe) { - Log.v(TAG, "Couldn't open file for restore: " + fnfe); - } catch (IOException ioe) { - Log.e(TAG, "Unable to process restore file: " + ioe); + File savedStateName = new File(mStateDir, packageName); + newStateName.renameTo(savedStateName); } catch (Exception e) { - Log.e(TAG, "Final exception guard in restore:"); - e.printStackTrace(); + Log.e(TAG, "Error restoring data for " + packageName, e); } } } @@ -1183,15 +1197,15 @@ class BackupManagerService extends IBackupManager.Stub { } } - public int performRestore(int token) throws android.os.RemoteException { + public int performRestore(long token, IRestoreObserver observer) + throws android.os.RemoteException { mContext.enforceCallingPermission("android.permission.BACKUP", "performRestore"); if (mRestoreSets != null) { for (int i = 0; i < mRestoreSets.length; i++) { if (token == mRestoreSets[i].token) { - Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE, - mRestoreTransport); - msg.arg1 = token; + Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); + msg.obj = new RestoreParams(mRestoreTransport, observer, token); mBackupHandler.sendMessage(msg); return 0; } @@ -1206,7 +1220,7 @@ class BackupManagerService extends IBackupManager.Stub { mContext.enforceCallingPermission("android.permission.BACKUP", "endRestoreSession"); - mRestoreTransport.endSession(); + mRestoreTransport.finishRestore(); mRestoreTransport = null; synchronized(BackupManagerService.this) { if (BackupManagerService.this.mActiveRestoreSession == this) { |
