Merge change 5006 into donut
* changes: Pass the originating app's versionCode along with a restore set
This commit is contained in:
@@ -78,11 +78,16 @@ public abstract class BackupAgent extends ContextWrapper {
|
|||||||
*
|
*
|
||||||
* @param data An open, read-only ParcelFileDescriptor pointing to a full snapshot
|
* @param data An open, read-only ParcelFileDescriptor pointing to a full snapshot
|
||||||
* of the application's data.
|
* of the application's data.
|
||||||
|
* @param appVersionCode The android:versionCode value of the application that backed
|
||||||
|
* up this particular data set. This makes it easier for an application's
|
||||||
|
* agent to distinguish among several possible older data versions when
|
||||||
|
* asked to perform the restore operation.
|
||||||
* @param newState An open, read/write ParcelFileDescriptor pointing to an empty
|
* @param newState An open, read/write ParcelFileDescriptor pointing to an empty
|
||||||
* file. The application should record the final backup state
|
* file. The application should record the final backup state
|
||||||
* here after restoring its data from dataFd.
|
* here after restoring its data from dataFd.
|
||||||
*/
|
*/
|
||||||
public abstract void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
|
public abstract void onRestore(BackupDataInput data, int appVersionCode,
|
||||||
|
ParcelFileDescriptor newState)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
|
|
||||||
@@ -121,13 +126,13 @@ public abstract class BackupAgent extends ContextWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doRestore(ParcelFileDescriptor data,
|
public void doRestore(ParcelFileDescriptor data, int appVersionCode,
|
||||||
ParcelFileDescriptor newState) throws RemoteException {
|
ParcelFileDescriptor newState) throws RemoteException {
|
||||||
// !!! TODO - real implementation; for now just invoke the callbacks directly
|
// !!! TODO - real implementation; for now just invoke the callbacks directly
|
||||||
Log.v(TAG, "doRestore() invoked");
|
Log.v(TAG, "doRestore() invoked");
|
||||||
BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
|
BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
|
||||||
try {
|
try {
|
||||||
BackupAgent.this.onRestore(input, newState);
|
BackupAgent.this.onRestore(input, appVersionCode, newState);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
|
Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
|
|||||||
@@ -53,6 +53,6 @@ public class FullBackupAgent extends BackupAgent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRestore(BackupDataInput data, ParcelFileDescriptor newState) {
|
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,9 +51,14 @@ interface IBackupAgent {
|
|||||||
* app's backup. This is to be a <i>replacement</i> of the app's
|
* app's backup. This is to be a <i>replacement</i> of the app's
|
||||||
* current data, not to be merged into it.
|
* current data, not to be merged into it.
|
||||||
*
|
*
|
||||||
|
* @param appVersionCode The android:versionCode attribute of the application
|
||||||
|
* that created this data set. This can help the agent distinguish among
|
||||||
|
* various historical backup content possibilities.
|
||||||
|
*
|
||||||
* @param newState Read-write file, empty when onRestore() is called,
|
* @param newState Read-write file, empty when onRestore() is called,
|
||||||
* that is to be written with the state description that holds after
|
* that is to be written with the state description that holds after
|
||||||
* the restore has been completed.
|
* the restore has been completed.
|
||||||
*/
|
*/
|
||||||
void doRestore(in ParcelFileDescriptor data, in ParcelFileDescriptor newState);
|
void doRestore(in ParcelFileDescriptor data, int appVersionCode,
|
||||||
|
in ParcelFileDescriptor newState);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ public class BackupHelperAgent extends BackupAgent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
|
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
mDispatcher.performRestore(data, newState);
|
mDispatcher.performRestore(data, appVersionCode, newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BackupHelperDispatcher getDispatcher() {
|
public BackupHelperDispatcher getDispatcher() {
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ public class BackupHelperDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void performRestore(BackupDataInput input, ParcelFileDescriptor newState)
|
public void performRestore(BackupDataInput input, int appVersionCode,
|
||||||
|
ParcelFileDescriptor newState)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
boolean alreadyComplained = false;
|
boolean alreadyComplained = false;
|
||||||
|
|
||||||
|
|||||||
@@ -33,19 +33,19 @@ interface IBackupManager {
|
|||||||
* Tell the system service that the caller has made changes to its
|
* Tell the system service that the caller has made changes to its
|
||||||
* data, and therefore needs to undergo an incremental backup pass.
|
* data, and therefore needs to undergo an incremental backup pass.
|
||||||
*/
|
*/
|
||||||
oneway void dataChanged(String packageName);
|
void dataChanged(String packageName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the Backup Manager Service that an agent has become available. This
|
* Notifies the Backup Manager Service that an agent has become available. This
|
||||||
* method is only invoked by the Activity Manager.
|
* method is only invoked by the Activity Manager.
|
||||||
*/
|
*/
|
||||||
oneway void agentConnected(String packageName, IBinder agent);
|
void agentConnected(String packageName, IBinder agent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify the Backup Manager Service that an agent has unexpectedly gone away.
|
* Notify the Backup Manager Service that an agent has unexpectedly gone away.
|
||||||
* This method is only invoked by the Activity Manager.
|
* This method is only invoked by the Activity Manager.
|
||||||
*/
|
*/
|
||||||
oneway void agentDisconnected(String packageName);
|
void agentDisconnected(String packageName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule an immediate backup attempt for all pending updates. This is
|
* Schedule an immediate backup attempt for all pending updates. This is
|
||||||
@@ -57,7 +57,7 @@ interface IBackupManager {
|
|||||||
*
|
*
|
||||||
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
|
* <p>Callers must hold the android.permission.BACKUP permission to use this method.
|
||||||
*/
|
*/
|
||||||
oneway void backupNow();
|
void backupNow();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identify the currently selected transport. Callers must hold the
|
* Identify the currently selected transport. Callers must hold the
|
||||||
|
|||||||
@@ -795,6 +795,16 @@ class BackupManagerService extends IBackupManager.Stub {
|
|||||||
private int mToken;
|
private int mToken;
|
||||||
private RestoreSet mImage;
|
private RestoreSet mImage;
|
||||||
|
|
||||||
|
class RestoreRequest {
|
||||||
|
public PackageInfo app;
|
||||||
|
public int storedAppVersion;
|
||||||
|
|
||||||
|
RestoreRequest(PackageInfo _app, int _version) {
|
||||||
|
app = _app;
|
||||||
|
storedAppVersion = _version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PerformRestoreThread(IBackupTransport transport, int restoreSetToken) {
|
PerformRestoreThread(IBackupTransport transport, int restoreSetToken) {
|
||||||
mTransport = transport;
|
mTransport = transport;
|
||||||
mToken = restoreSetToken;
|
mToken = restoreSetToken;
|
||||||
@@ -840,11 +850,13 @@ class BackupManagerService extends IBackupManager.Stub {
|
|||||||
mPackageManager, allAgentApps());
|
mPackageManager, allAgentApps());
|
||||||
PackageInfo pmApp = new PackageInfo();
|
PackageInfo pmApp = new PackageInfo();
|
||||||
pmApp.packageName = PACKAGE_MANAGER_SENTINEL;
|
pmApp.packageName = PACKAGE_MANAGER_SENTINEL;
|
||||||
processOneRestore(pmApp, IBackupAgent.Stub.asInterface(pmAgent.onBind()));
|
// !!! 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
|
// build the set of apps we will attempt to restore
|
||||||
PackageInfo[] packages = mTransport.getAppSet(mImage.token);
|
PackageInfo[] packages = mTransport.getAppSet(mImage.token);
|
||||||
HashSet<PackageInfo> appsToRestore = new HashSet<PackageInfo>();
|
HashSet<RestoreRequest> appsToRestore = new HashSet<RestoreRequest>();
|
||||||
for (PackageInfo pkg: packages) {
|
for (PackageInfo pkg: packages) {
|
||||||
// get the real PackageManager idea of the package
|
// get the real PackageManager idea of the package
|
||||||
PackageInfo app = isRestorable(pkg);
|
PackageInfo app = isRestorable(pkg);
|
||||||
@@ -858,7 +870,8 @@ class BackupManagerService extends IBackupManager.Stub {
|
|||||||
+ " compatible with app version "
|
+ " compatible with app version "
|
||||||
+ app.versionCode);
|
+ app.versionCode);
|
||||||
if (signaturesMatch(info.signatures, app.signatures)) {
|
if (signaturesMatch(info.signatures, app.signatures)) {
|
||||||
appsToRestore.add(app);
|
appsToRestore.add(
|
||||||
|
new RestoreRequest(app, info.versionCode));
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Sig mismatch restoring "
|
Log.w(TAG, "Sig mismatch restoring "
|
||||||
+ app.packageName);
|
+ app.packageName);
|
||||||
@@ -896,8 +909,9 @@ class BackupManagerService extends IBackupManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// restore each app in the queue
|
// restore each app in the queue
|
||||||
void doQueuedRestores(HashSet<PackageInfo> appsToRestore) {
|
void doQueuedRestores(HashSet<RestoreRequest> appsToRestore) {
|
||||||
for (PackageInfo app : appsToRestore) {
|
for (RestoreRequest req : appsToRestore) {
|
||||||
|
PackageInfo app = req.app;
|
||||||
Log.d(TAG, "starting agent for restore of " + app);
|
Log.d(TAG, "starting agent for restore of " + app);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -908,7 +922,7 @@ class BackupManagerService extends IBackupManager.Stub {
|
|||||||
IBackupAgent agent = bindToAgentSynchronous(app.applicationInfo,
|
IBackupAgent agent = bindToAgentSynchronous(app.applicationInfo,
|
||||||
IApplicationThread.BACKUP_MODE_RESTORE);
|
IApplicationThread.BACKUP_MODE_RESTORE);
|
||||||
if (agent != null) {
|
if (agent != null) {
|
||||||
processOneRestore(app, agent);
|
processOneRestore(app, req.storedAppVersion, agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unbind even on timeout, just in case
|
// unbind even on timeout, just in case
|
||||||
@@ -925,7 +939,7 @@ class BackupManagerService extends IBackupManager.Stub {
|
|||||||
|
|
||||||
// Do the guts of a restore of one application, derived from the 'mImage'
|
// Do the guts of a restore of one application, derived from the 'mImage'
|
||||||
// restore set via the 'mTransport' transport.
|
// restore set via the 'mTransport' transport.
|
||||||
void processOneRestore(PackageInfo app, IBackupAgent agent) {
|
void processOneRestore(PackageInfo app, int storedAppVersion, IBackupAgent agent) {
|
||||||
// !!! TODO: actually run the restore through mTransport
|
// !!! TODO: actually run the restore through mTransport
|
||||||
final String packageName = app.packageName;
|
final String packageName = app.packageName;
|
||||||
|
|
||||||
@@ -961,7 +975,7 @@ class BackupManagerService extends IBackupManager.Stub {
|
|||||||
|
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
agent.doRestore(backupData, newState);
|
agent.doRestore(backupData, storedAppVersion, newState);
|
||||||
success = true;
|
success = true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Restore failed for " + packageName);
|
Log.e(TAG, "Restore failed for " + packageName);
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ public class PackageManagerBackupAgent extends BackupAgent {
|
|||||||
// "Restore" here is a misnomer. What we're really doing is reading back the
|
// "Restore" here is a misnomer. What we're really doing is reading back the
|
||||||
// set of app signatures associated with each backed-up app in this restore
|
// set of app signatures associated with each backed-up app in this restore
|
||||||
// image. We'll use those later to determine what we can legitimately restore.
|
// image. We'll use those later to determine what we can legitimately restore.
|
||||||
public void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
|
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
List<ApplicationInfo> restoredApps = new ArrayList<ApplicationInfo>();
|
List<ApplicationInfo> restoredApps = new ArrayList<ApplicationInfo>();
|
||||||
HashMap<String, Metadata> sigMap = new HashMap<String, Metadata>();
|
HashMap<String, Metadata> sigMap = new HashMap<String, Metadata>();
|
||||||
|
|||||||
@@ -164,7 +164,8 @@ public class BackupTestActivity extends ListActivity
|
|||||||
new File(getFilesDir(), "restore_state"),
|
new File(getFilesDir(), "restore_state"),
|
||||||
ParcelFileDescriptor.MODE_READ_WRITE|ParcelFileDescriptor.MODE_CREATE|
|
ParcelFileDescriptor.MODE_READ_WRITE|ParcelFileDescriptor.MODE_CREATE|
|
||||||
ParcelFileDescriptor.MODE_TRUNCATE);
|
ParcelFileDescriptor.MODE_TRUNCATE);
|
||||||
dispatch.performRestore(data, state);
|
// TODO: a more plausable synthetic stored-data version number
|
||||||
|
dispatch.performRestore(data, 0, state);
|
||||||
dataFile.close();
|
dataFile.close();
|
||||||
state.close();
|
state.close();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
|
|||||||
Reference in New Issue
Block a user