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 PackageInfo pkgInfo;
public int pmToken; // in post-install restore, the PM's token for this transaction
public boolean needFullBackup;
RestoreParams(IBackupTransport _transport, IRestoreObserver _obs,
long _token, PackageInfo _pkg, int _pmToken) {
long _token, PackageInfo _pkg, int _pmToken, boolean _needFullBackup) {
transport = _transport;
observer = _obs;
token = _token;
pkgInfo = _pkg;
pmToken = _pmToken;
needFullBackup = _needFullBackup;
}
RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token) {
RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token,
boolean _needFullBackup) {
transport = _transport;
observer = _obs;
token = _token;
pkgInfo = null;
pmToken = 0;
needFullBackup = _needFullBackup;
}
}
@ -323,7 +327,8 @@ class BackupManagerService extends IBackupManager.Stub {
RestoreParams params = (RestoreParams)msg.obj;
Slog.d(TAG, "MSG_RUN_RESTORE observer=" + 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;
}
@ -1559,6 +1564,7 @@ class BackupManagerService extends IBackupManager.Stub {
private PackageInfo mTargetPackage;
private File mStateDir;
private int mPmToken;
private boolean mNeedFullBackup;
class RestoreRequest {
public PackageInfo app;
@ -1571,12 +1577,14 @@ class BackupManagerService extends IBackupManager.Stub {
}
PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer,
long restoreSetToken, PackageInfo targetPackage, int pmToken) {
long restoreSetToken, PackageInfo targetPackage, int pmToken,
boolean needFullBackup) {
mTransport = transport;
mObserver = observer;
mToken = restoreSetToken;
mTargetPackage = targetPackage;
mPmToken = pmToken;
mNeedFullBackup = needFullBackup;
try {
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
pmAgent = new PackageManagerBackupAgent(
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
// 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
try {
processOneRestore(packageInfo, metaInfo.versionCode, agent);
processOneRestore(packageInfo, metaInfo.versionCode, agent,
mNeedFullBackup);
++count;
} finally {
// 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().
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
final String packageName = app.packageName;
@ -1900,6 +1911,14 @@ class BackupManagerService extends IBackupManager.Stub {
try { if (newState != null) newState.close(); } catch (IOException e) {}
backupData = newState = null;
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();
Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
msg.obj = new RestoreParams(getTransport(mCurrentTransport), null,
restoreSet, pkg, token);
restoreSet, pkg, token, true);
mBackupHandler.sendMessage(msg);
} else {
// 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();
mWakelock.acquire();
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);
Binder.restoreCallingIdentity(oldId);
return 0;
@ -2581,7 +2600,7 @@ class BackupManagerService extends IBackupManager.Stub {
long oldId = Binder.clearCallingIdentity();
mWakelock.acquire();
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);
Binder.restoreCallingIdentity(oldId);
return 0;