DO NOT MERGE : Ensure that the first post-restore backup pass is correct

Some restore passes bring an ancestral dataset to the application, but
others instead act to bring an app back into sync with its own most-
recently-saved data.  In the latter case the state file written by the
app after the restore is a correct basis for generating future backup
deltas, but in the former case it is not.

The app should not be required to distinguish between these cases;
the framework has all the information necessary to handle the saved
state correctly following any flavor of restore operation.  This
patch makes the Backup Manager properly cause a full backup pass
following an ancestral-dataset restore.  After a current-set
restore the saved state file is an accurate description for
purposes of continued backup operations, so is preserved.

(Cherrypick from master to gingerbread)

Change-Id: I4bc4e8782a168ecc0795107a340bdbb35060730e
This commit is contained in:
Chris Tate
2010-10-29 12:57:04 -07:00
parent 6ec91731cb
commit bbff7ed44b

View File

@ -198,22 +198,26 @@ class BackupManagerService extends IBackupManager.Stub {
public long token; public long token;
public PackageInfo pkgInfo; public PackageInfo pkgInfo;
public int pmToken; // in post-install restore, the PM's token for this transaction public int pmToken; // in post-install restore, the PM's token for this transaction
public boolean needFullBackup;
RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, RestoreParams(IBackupTransport _transport, IRestoreObserver _obs,
long _token, PackageInfo _pkg, int _pmToken) { long _token, PackageInfo _pkg, int _pmToken, boolean _needFullBackup) {
transport = _transport; transport = _transport;
observer = _obs; observer = _obs;
token = _token; token = _token;
pkgInfo = _pkg; pkgInfo = _pkg;
pmToken = _pmToken; pmToken = _pmToken;
needFullBackup = _needFullBackup;
} }
RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token) { RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token,
boolean _needFullBackup) {
transport = _transport; transport = _transport;
observer = _obs; observer = _obs;
token = _token; token = _token;
pkgInfo = null; pkgInfo = null;
pmToken = 0; pmToken = 0;
needFullBackup = _needFullBackup;
} }
} }
@ -323,7 +327,8 @@ class BackupManagerService extends IBackupManager.Stub {
RestoreParams params = (RestoreParams)msg.obj; RestoreParams params = (RestoreParams)msg.obj;
Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer); Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
(new PerformRestoreTask(params.transport, params.observer, (new PerformRestoreTask(params.transport, params.observer,
params.token, params.pkgInfo, params.pmToken)).run(); params.token, params.pkgInfo, params.pmToken,
params.needFullBackup)).run();
break; break;
} }
@ -1559,6 +1564,7 @@ class BackupManagerService extends IBackupManager.Stub {
private PackageInfo mTargetPackage; private PackageInfo mTargetPackage;
private File mStateDir; private File mStateDir;
private int mPmToken; private int mPmToken;
private boolean mNeedFullBackup;
class RestoreRequest { class RestoreRequest {
public PackageInfo app; public PackageInfo app;
@ -1571,12 +1577,14 @@ class BackupManagerService extends IBackupManager.Stub {
} }
PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer, PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer,
long restoreSetToken, PackageInfo targetPackage, int pmToken) { long restoreSetToken, PackageInfo targetPackage, int pmToken,
boolean needFullBackup) {
mTransport = transport; mTransport = transport;
mObserver = observer; mObserver = observer;
mToken = restoreSetToken; mToken = restoreSetToken;
mTargetPackage = targetPackage; mTargetPackage = targetPackage;
mPmToken = pmToken; mPmToken = pmToken;
mNeedFullBackup = needFullBackup;
try { try {
mStateDir = new File(mBaseStateDir, transport.transportDirName()); mStateDir = new File(mBaseStateDir, transport.transportDirName());
@ -1654,7 +1662,8 @@ class BackupManagerService extends IBackupManager.Stub {
// Pull the Package Manager metadata from the restore set first // Pull the Package Manager metadata from the restore set first
pmAgent = new PackageManagerBackupAgent( pmAgent = new PackageManagerBackupAgent(
mPackageManager, agentPackages); mPackageManager, agentPackages);
processOneRestore(omPackage, 0, IBackupAgent.Stub.asInterface(pmAgent.onBind())); processOneRestore(omPackage, 0, IBackupAgent.Stub.asInterface(pmAgent.onBind()),
mNeedFullBackup);
// Verify that the backup set includes metadata. If not, we can't do // Verify that the backup set includes metadata. If not, we can't do
// signature/version verification etc, so we simply do not proceed with // signature/version verification etc, so we simply do not proceed with
@ -1751,7 +1760,8 @@ class BackupManagerService extends IBackupManager.Stub {
// And then finally run the restore on this agent // And then finally run the restore on this agent
try { try {
processOneRestore(packageInfo, metaInfo.versionCode, agent); processOneRestore(packageInfo, metaInfo.versionCode, agent,
mNeedFullBackup);
++count; ++count;
} finally { } finally {
// unbind and tidy up even on timeout or failure, just in case // unbind and tidy up even on timeout or failure, just in case
@ -1821,7 +1831,8 @@ class BackupManagerService extends IBackupManager.Stub {
} }
// Do the guts of a restore of one application, using mTransport.getRestoreData(). // Do the guts of a restore of one application, using mTransport.getRestoreData().
void processOneRestore(PackageInfo app, int appVersionCode, IBackupAgent agent) { void processOneRestore(PackageInfo app, int appVersionCode, IBackupAgent agent,
boolean needFullBackup) {
// !!! TODO: actually run the restore through mTransport // !!! TODO: actually run the restore through mTransport
final String packageName = app.packageName; final String packageName = app.packageName;
@ -1900,6 +1911,14 @@ class BackupManagerService extends IBackupManager.Stub {
try { if (newState != null) newState.close(); } catch (IOException e) {} try { if (newState != null) newState.close(); } catch (IOException e) {}
backupData = newState = null; backupData = newState = null;
mCurrentOperations.delete(token); mCurrentOperations.delete(token);
// If we know a priori that we'll need to perform a full post-restore backup
// pass, clear the new state file data. This means we're discarding work that
// was just done by the app's agent, but this way the agent doesn't need to
// take any special action based on global device state.
if (needFullBackup) {
newStateName.delete();
}
} }
} }
} }
@ -2385,7 +2404,7 @@ class BackupManagerService extends IBackupManager.Stub {
mWakelock.acquire(); mWakelock.acquire();
Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
msg.obj = new RestoreParams(getTransport(mCurrentTransport), null, msg.obj = new RestoreParams(getTransport(mCurrentTransport), null,
restoreSet, pkg, token); restoreSet, pkg, token, true);
mBackupHandler.sendMessage(msg); mBackupHandler.sendMessage(msg);
} else { } else {
// Auto-restore disabled or no way to attempt a restore; just tell the Package // Auto-restore disabled or no way to attempt a restore; just tell the Package
@ -2516,7 +2535,7 @@ class BackupManagerService extends IBackupManager.Stub {
long oldId = Binder.clearCallingIdentity(); long oldId = Binder.clearCallingIdentity();
mWakelock.acquire(); mWakelock.acquire();
Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
msg.obj = new RestoreParams(mRestoreTransport, observer, token); msg.obj = new RestoreParams(mRestoreTransport, observer, token, true);
mBackupHandler.sendMessage(msg); mBackupHandler.sendMessage(msg);
Binder.restoreCallingIdentity(oldId); Binder.restoreCallingIdentity(oldId);
return 0; return 0;
@ -2581,7 +2600,7 @@ class BackupManagerService extends IBackupManager.Stub {
long oldId = Binder.clearCallingIdentity(); long oldId = Binder.clearCallingIdentity();
mWakelock.acquire(); mWakelock.acquire();
Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE); Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
msg.obj = new RestoreParams(mRestoreTransport, observer, token, app, 0); msg.obj = new RestoreParams(mRestoreTransport, observer, token, app, 0, false);
mBackupHandler.sendMessage(msg); mBackupHandler.sendMessage(msg);
Binder.restoreCallingIdentity(oldId); Binder.restoreCallingIdentity(oldId);
return 0; return 0;