Pass the originating app's versionCode along with a restore set

This change amends the doRestore() / onRestore() interface to backup agents to
provide the integer android:versionCode of the app that stored the backup set.
This should help agents figure out how to handle whatever historical data set
they're handed at restore time.
diff --git a/core/java/android/app/BackupAgent.java b/core/java/android/app/BackupAgent.java
index 85c001c..e810775 100644
--- a/core/java/android/app/BackupAgent.java
+++ b/core/java/android/app/BackupAgent.java
@@ -78,11 +78,16 @@
      *
      * @param data An open, read-only ParcelFileDescriptor pointing to a full snapshot
      *             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
      *                 file.  The application should record the final backup state
      *                 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;
 
 
@@ -121,13 +126,13 @@
             }
         }
 
-        public void doRestore(ParcelFileDescriptor data,
+        public void doRestore(ParcelFileDescriptor data, int appVersionCode,
                 ParcelFileDescriptor newState) throws RemoteException {
             // !!! TODO - real implementation; for now just invoke the callbacks directly
             Log.v(TAG, "doRestore() invoked");
             BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
             try {
-                BackupAgent.this.onRestore(input, newState);
+                BackupAgent.this.onRestore(input, appVersionCode, newState);
             } catch (IOException ex) {
                 Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
                 throw new RuntimeException(ex);
diff --git a/core/java/android/app/FullBackupAgent.java b/core/java/android/app/FullBackupAgent.java
index bc6bb15..d89db96 100644
--- a/core/java/android/app/FullBackupAgent.java
+++ b/core/java/android/app/FullBackupAgent.java
@@ -53,6 +53,6 @@
     }
 
     @Override
-    public void onRestore(BackupDataInput data, ParcelFileDescriptor newState) {
+    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) {
     }
 }
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index bb9f008..9b0550f 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -51,9 +51,14 @@
      *        app's backup.  This is to be a <i>replacement</i> of the app's
      *        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,
      *        that is to be written with the state description that holds after
      *        the restore has been completed.
      */
-    void doRestore(in ParcelFileDescriptor data, in ParcelFileDescriptor newState);
+    void doRestore(in ParcelFileDescriptor data, int appVersionCode,
+            in ParcelFileDescriptor newState);
 }
diff --git a/core/java/android/backup/BackupHelperAgent.java b/core/java/android/backup/BackupHelperAgent.java
index f7eb1b8..3720d50 100644
--- a/core/java/android/backup/BackupHelperAgent.java
+++ b/core/java/android/backup/BackupHelperAgent.java
@@ -39,9 +39,9 @@
     }
 
     @Override
-    public void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
+    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
             throws IOException {
-        mDispatcher.performRestore(data, newState);
+        mDispatcher.performRestore(data, appVersionCode, newState);
     }
 
     public BackupHelperDispatcher getDispatcher() {
diff --git a/core/java/android/backup/BackupHelperDispatcher.java b/core/java/android/backup/BackupHelperDispatcher.java
index e9a8f71..b25c3e3 100644
--- a/core/java/android/backup/BackupHelperDispatcher.java
+++ b/core/java/android/backup/BackupHelperDispatcher.java
@@ -46,7 +46,8 @@
         }
     }
 
-    public void performRestore(BackupDataInput input, ParcelFileDescriptor newState)
+    public void performRestore(BackupDataInput input, int appVersionCode,
+            ParcelFileDescriptor newState)
             throws IOException {
         boolean alreadyComplained = false;
 
diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl
index efc664c..d6283d0 100644
--- a/core/java/android/backup/IBackupManager.aidl
+++ b/core/java/android/backup/IBackupManager.aidl
@@ -33,19 +33,19 @@
      * Tell the system service that the caller has made changes to its
      * 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
      * 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.
      * 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
@@ -57,7 +57,7 @@
      *
      * <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
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index c60f981..197404e 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -795,6 +795,16 @@
         private int mToken;
         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) {
             mTransport = transport;
             mToken = restoreSetToken;
@@ -840,11 +850,13 @@
                                 mPackageManager, allAgentApps());
                         PackageInfo pmApp = new PackageInfo();
                         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
                         PackageInfo[] packages = mTransport.getAppSet(mImage.token);
-                        HashSet<PackageInfo> appsToRestore = new HashSet<PackageInfo>();
+                        HashSet<RestoreRequest> appsToRestore = new HashSet<RestoreRequest>();
                         for (PackageInfo pkg: packages) {
                             // get the real PackageManager idea of the package
                             PackageInfo app = isRestorable(pkg);
@@ -858,7 +870,8 @@
                                                 + " compatible with app version "
                                                 + app.versionCode);
                                         if (signaturesMatch(info.signatures, app.signatures)) {
-                                            appsToRestore.add(app);
+                                            appsToRestore.add(
+                                                    new RestoreRequest(app, info.versionCode));
                                         } else {
                                             Log.w(TAG, "Sig mismatch restoring "
                                                     + app.packageName);
@@ -896,8 +909,9 @@
         }
 
         // restore each app in the queue
-        void doQueuedRestores(HashSet<PackageInfo> appsToRestore) {
-            for (PackageInfo app : appsToRestore) {
+        void doQueuedRestores(HashSet<RestoreRequest> appsToRestore) {
+            for (RestoreRequest req : appsToRestore) {
+                PackageInfo app = req.app;
                 Log.d(TAG, "starting agent for restore of " + app);
 
                 try {
@@ -908,7 +922,7 @@
                     IBackupAgent agent = bindToAgentSynchronous(app.applicationInfo,
                             IApplicationThread.BACKUP_MODE_RESTORE);
                     if (agent != null) {
-                        processOneRestore(app, agent);
+                        processOneRestore(app, req.storedAppVersion, agent);
                     }
 
                     // unbind even on timeout, just in case
@@ -925,7 +939,7 @@
 
         // Do the guts of a restore of one application, derived from the 'mImage'
         // 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
             final String packageName = app.packageName;
 
@@ -961,7 +975,7 @@
 
                 boolean success = false;
                 try {
-                    agent.doRestore(backupData, newState);
+                    agent.doRestore(backupData, storedAppVersion, newState);
                     success = true;
                 } catch (Exception e) {
                     Log.e(TAG, "Restore failed for " + packageName);
diff --git a/services/java/com/android/server/PackageManagerBackupAgent.java b/services/java/com/android/server/PackageManagerBackupAgent.java
index 9422878..d620eb1 100644
--- a/services/java/com/android/server/PackageManagerBackupAgent.java
+++ b/services/java/com/android/server/PackageManagerBackupAgent.java
@@ -192,7 +192,7 @@
     // "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
     // 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 {
         List<ApplicationInfo> restoredApps = new ArrayList<ApplicationInfo>();
         HashMap<String, Metadata> sigMap = new HashMap<String, Metadata>();
diff --git a/tests/backup/src/com/android/backuptest/BackupTestActivity.java b/tests/backup/src/com/android/backuptest/BackupTestActivity.java
index 69da761..7f30c91 100644
--- a/tests/backup/src/com/android/backuptest/BackupTestActivity.java
+++ b/tests/backup/src/com/android/backuptest/BackupTestActivity.java
@@ -164,7 +164,8 @@
                             new File(getFilesDir(), "restore_state"),
                             ParcelFileDescriptor.MODE_READ_WRITE|ParcelFileDescriptor.MODE_CREATE|
                             ParcelFileDescriptor.MODE_TRUNCATE);
-                    dispatch.performRestore(data, state);
+                    // TODO: a more plausable synthetic stored-data version number
+                    dispatch.performRestore(data, 0, state);
                     dataFile.close();
                     state.close();
                 } catch (IOException ex) {