Merge changes Ic2bb4798,I2a409de2,I88a50a0e,Ia69342a4,Ia6548e4d, ...

* changes:
  Use "commit" instead of "execute" for rollbacks.
  Rename PACKAGE_ROLLBACK_EXECUTED to ROLLBACK_COMMITTED.
  Remove unused RollbackManager APIs.
  Use RollbackManager.getAvailableRollbacks in RollbackTest
  Use new RollbackManager API in RollbackPackageHealthObserver.
  Add RollbackManager.getAvailableRollbacks API.
  Include all relevant packages in RollbackInfo.
diff --git a/api/system-current.txt b/api/system-current.txt
index be07151..31e6c6c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1303,13 +1303,13 @@
     field public static final String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
     field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_SPECIAL_APP_ACCESSES = "android.intent.action.MANAGE_SPECIAL_APP_ACCESSES";
     field public static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
-    field public static final String ACTION_PACKAGE_ROLLBACK_EXECUTED = "android.intent.action.PACKAGE_ROLLBACK_EXECUTED";
     field public static final String ACTION_PRE_BOOT_COMPLETED = "android.intent.action.PRE_BOOT_COMPLETED";
     field public static final String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
     field public static final String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
     field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_APP_PERMISSION_USAGE = "android.intent.action.REVIEW_APP_PERMISSION_USAGE";
     field public static final String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
     field public static final String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE";
+    field public static final String ACTION_ROLLBACK_COMMITTED = "android.intent.action.ROLLBACK_COMMITTED";
     field public static final String ACTION_SHOW_SUSPENDED_APP_DETAILS = "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
     field @Deprecated public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
     field public static final String ACTION_SPLIT_CONFIGURATION_CHANGED = "android.intent.action.SPLIT_CONFIGURATION_CHANGED";
@@ -1695,18 +1695,17 @@
 
   public final class RollbackInfo implements android.os.Parcelable {
     method public int describeContents();
+    method public java.util.List<android.content.rollback.PackageRollbackInfo> getPackages();
     method public int getRollbackId();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.rollback.RollbackInfo> CREATOR;
-    field public final android.content.rollback.PackageRollbackInfo targetPackage;
   }
 
   public final class RollbackManager {
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void executeRollback(@NonNull android.content.rollback.RollbackInfo, @NonNull android.content.IntentSender);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void commitRollback(@NonNull android.content.rollback.RollbackInfo, @NonNull android.content.IntentSender);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @Nullable public android.content.rollback.RollbackInfo getAvailableRollback(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<java.lang.String> getPackagesWithAvailableRollbacks();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyExecutedRollbacks();
+    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
+    method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
     method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void reloadPersistedData();
   }
 
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 9e7aaf6..22f73db 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2375,8 +2375,7 @@
     public static final String ACTION_PACKAGE_ENABLE_ROLLBACK =
             "android.intent.action.PACKAGE_ENABLE_ROLLBACK";
     /**
-     * Broadcast Action: An existing version of an application package has been
-     * rolled back to a previous version.
+     * Broadcast Action: A rollback has been committed.
      *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
@@ -2385,8 +2384,8 @@
      */
     @SystemApi
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_PACKAGE_ROLLBACK_EXECUTED =
-            "android.intent.action.PACKAGE_ROLLBACK_EXECUTED";
+    public static final String ACTION_ROLLBACK_COMMITTED =
+            "android.intent.action.ROLLBACK_COMMITTED";
     /**
      * @hide
      * Broadcast Action: Ask system services if there is any reason to
diff --git a/core/java/android/content/rollback/IRollbackManager.aidl b/core/java/android/content/rollback/IRollbackManager.aidl
index 420bcb6..63d75a0 100644
--- a/core/java/android/content/rollback/IRollbackManager.aidl
+++ b/core/java/android/content/rollback/IRollbackManager.aidl
@@ -17,17 +17,13 @@
 package android.content.rollback;
 
 import android.content.pm.ParceledListSlice;
-import android.content.pm.StringParceledListSlice;
 import android.content.rollback.RollbackInfo;
 import android.content.IntentSender;
 
 /** {@hide} */
 interface IRollbackManager {
 
-    RollbackInfo getAvailableRollback(String packageName);
-
-    StringParceledListSlice getPackagesWithAvailableRollbacks();
-
+    ParceledListSlice getAvailableRollbacks();
     ParceledListSlice getRecentlyExecutedRollbacks();
 
     void executeRollback(in RollbackInfo rollback, String callerPackageName,
diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java
index 0803a7c..8532b5a 100644
--- a/core/java/android/content/rollback/RollbackInfo.java
+++ b/core/java/android/content/rollback/RollbackInfo.java
@@ -20,6 +20,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.List;
+
 /**
  * Information about a set of packages that can be, or already have been
  * rolled back together.
@@ -34,25 +36,20 @@
      */
     private final int mRollbackId;
 
-    /**
-     * The package that needs to be rolled back.
-     */
-    public final PackageRollbackInfo targetPackage;
+    private final List<PackageRollbackInfo> mPackages;
 
-    // TODO: Add a list of additional packages rolled back due to atomic
-    // install dependencies when rollback of atomic installs is supported.
     // TODO: Add a flag to indicate if reboot is required, when rollback of
     // staged installs is supported.
 
     /** @hide */
-    public RollbackInfo(int rollbackId, PackageRollbackInfo targetPackage) {
+    public RollbackInfo(int rollbackId, List<PackageRollbackInfo> packages) {
         this.mRollbackId = rollbackId;
-        this.targetPackage = targetPackage;
+        this.mPackages = packages;
     }
 
     private RollbackInfo(Parcel in) {
         mRollbackId = in.readInt();
-        targetPackage = PackageRollbackInfo.CREATOR.createFromParcel(in);
+        mPackages = in.createTypedArrayList(PackageRollbackInfo.CREATOR);
     }
 
     /**
@@ -62,6 +59,13 @@
         return mRollbackId;
     }
 
+    /**
+     * Returns the list of package that are rolled back.
+     */
+    public List<PackageRollbackInfo> getPackages() {
+        return mPackages;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -70,7 +74,7 @@
     @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mRollbackId);
-        targetPackage.writeToParcel(out, flags);
+        out.writeTypedList(mPackages);
     }
 
     public static final Parcelable.Creator<RollbackInfo> CREATOR =
diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java
index c1c0bc1..2566ac5 100644
--- a/core/java/android/content/rollback/RollbackManager.java
+++ b/core/java/android/content/rollback/RollbackManager.java
@@ -17,7 +17,6 @@
 package android.content.rollback;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -50,55 +49,26 @@
     }
 
     /**
-     * Returns the rollback currently available to be executed for the given
-     * package.
-     * <p>
-     * The returned RollbackInfo describes what packages would be rolled back,
-     * including package version codes before and after rollback. The rollback
-     * can be initiated using {@link #executeRollback(RollbackInfo,IntentSender)}.
-     * <p>
-     * TODO: What if there is no package installed on device for packageName?
+     * Returns a list of all currently available rollbacks.
      *
-     * @param packageName name of the package to get the availble RollbackInfo for.
-     * @return the rollback available for the package, or null if no rollback
-     *         is available for the package.
      * @throws SecurityException if the caller does not have the
      *            MANAGE_ROLLBACKS permission.
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
-    public @Nullable RollbackInfo getAvailableRollback(@NonNull String packageName) {
+    public List<RollbackInfo> getAvailableRollbacks() {
         try {
-            return mBinder.getAvailableRollback(packageName);
+            return mBinder.getAvailableRollbacks().getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Gets the names of packages that are available for rollback.
-     * Call {@link #getAvailableRollback(String)} to get more information
-     * about the rollback available for a particular package.
-     *
-     * @return the names of packages that are available for rollback.
-     * @throws SecurityException if the caller does not have the
-     *            MANAGE_ROLLBACKS permission.
-     */
-    @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
-    public @NonNull List<String> getPackagesWithAvailableRollbacks() {
-        try {
-            return mBinder.getPackagesWithAvailableRollbacks().getList();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-
-    /**
-     * Gets the list of all recently executed rollbacks.
+     * Gets the list of all recently committed rollbacks.
      * This is for the purposes of preventing re-install of a bad version of a
-     * package.
+     * package and monitoring the status of a staged rollback.
      * <p>
-     * Returns an empty list if there are no recently executed rollbacks.
+     * Returns an empty list if there are no recently committed rollbacks.
      * <p>
      * To avoid having to keep around complete rollback history forever on a
      * device, the returned list of rollbacks is only guaranteed to include
@@ -107,12 +77,12 @@
      * (without the possibility of rollback) to a higher version code than was
      * rolled back from.
      *
-     * @return the recently executed rollbacks
+     * @return the recently committed rollbacks
      * @throws SecurityException if the caller does not have the
      *            MANAGE_ROLLBACKS permission.
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
-    public @NonNull List<RollbackInfo> getRecentlyExecutedRollbacks() {
+    public @NonNull List<RollbackInfo> getRecentlyCommittedRollbacks() {
         try {
             return mBinder.getRecentlyExecutedRollbacks().getList();
         } catch (RemoteException e) {
@@ -121,25 +91,24 @@
     }
 
     /**
-     * Execute the given rollback, rolling back all versions of the packages
-     * to the last good versions previously installed on the device as
-     * specified in the given rollback object. The rollback will fail if any
-     * of the installed packages or available rollbacks are inconsistent with
-     * the versions specified in the given rollback object, which can happen
-     * if a package has been updated or a rollback expired since the rollback
-     * object was retrieved from {@link #getAvailableRollback(String)}.
+     * Commit the rollback with given id, rolling back all versions of the
+     * packages to the last good versions previously installed on the device
+     * as specified in the corresponding RollbackInfo object. The
+     * rollback will fail if any of the installed packages or available
+     * rollbacks are inconsistent with the versions specified in the given
+     * rollback object, which can happen if a package has been updated or a
+     * rollback expired since the rollback object was retrieved from
+     * {@link #getAvailableRollbacks()}.
      * <p>
      * TODO: Specify the returns status codes.
-     * TODO: What happens in case reboot is required for the rollback to take
-     * effect for staged installs?
      *
-     * @param rollback to execute
+     * @param rollback to commit
      * @param statusReceiver where to deliver the results
      * @throws SecurityException if the caller does not have the
      *            MANAGE_ROLLBACKS permission.
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS)
-    public void executeRollback(@NonNull RollbackInfo rollback,
+    public void commitRollback(@NonNull RollbackInfo rollback,
             @NonNull IntentSender statusReceiver) {
         try {
             mBinder.executeRollback(rollback, mCallerPackageName, statusReceiver);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4a54bd7..893a607 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -43,7 +43,7 @@
     <protected-broadcast android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_CHANGED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_ENABLE_ROLLBACK" />
-    <protected-broadcast android:name="android.intent.action.PACKAGE_ROLLBACK_EXECUTED" />
+    <protected-broadcast android:name="android.intent.action.ROLLBACK_COMMITTED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_RESTARTED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_LAUNCH" />
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 8b4c410..6487bd7 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -28,7 +28,6 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
 import android.content.pm.ParceledListSlice;
-import android.content.pm.StringParceledListSlice;
 import android.content.pm.VersionedPackage;
 import android.content.rollback.IRollbackManager;
 import android.content.rollback.PackageRollbackInfo;
@@ -56,12 +55,10 @@
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
-import java.util.Set;
 
 /**
  * Implementation of service that manages APK level rollbacks.
@@ -200,48 +197,20 @@
     }
 
     @Override
-    public RollbackInfo getAvailableRollback(String packageName) {
+    public ParceledListSlice getAvailableRollbacks() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.MANAGE_ROLLBACKS,
-                "getAvailableRollback");
+                "getAvailableRollbacks");
 
-        RollbackData data = getRollbackForPackage(packageName);
-        if (data == null) {
-            return null;
-        }
-
-        // Note: The rollback for the package ought to be for the currently
-        // installed version, otherwise the rollback data is out of date. In
-        // that rare case, we'll check when we execute the rollback whether
-        // it's out of date or not, so no need to check package versions here.
-
-        for (PackageRollbackInfo info : data.packages) {
-            if (info.getPackageName().equals(packageName)) {
-                // TODO: Once the RollbackInfo API supports info about
-                // dependant packages, add that info here.
-                return new RollbackInfo(data.rollbackId, info);
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public StringParceledListSlice getPackagesWithAvailableRollbacks() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.MANAGE_ROLLBACKS,
-                "getPackagesWithAvailableRollbacks");
-
-        final Set<String> packageNames = new HashSet<>();
         synchronized (mLock) {
             ensureRollbackDataLoadedLocked();
+            List<RollbackInfo> rollbacks = new ArrayList<>();
             for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
                 RollbackData data = mAvailableRollbacks.get(i);
-                for (PackageRollbackInfo info : data.packages) {
-                    packageNames.add(info.getPackageName());
-                }
+                rollbacks.add(new RollbackInfo(data.rollbackId, data.packages));
             }
+            return new ParceledListSlice<>(rollbacks);
         }
-        return new StringParceledListSlice(new ArrayList<>(packageNames));
     }
 
     @Override
@@ -279,18 +248,11 @@
      */
     private void executeRollbackInternal(RollbackInfo rollback,
             String callerPackageName, IntentSender statusReceiver) {
-        String targetPackageName = rollback.targetPackage.getPackageName();
-        Log.i(TAG, "Initiating rollback of " + targetPackageName);
+        Log.i(TAG, "Initiating rollback");
 
-        // Get the latest RollbackData for the target package.
-        final RollbackData data = getRollbackForPackage(targetPackageName);
+        RollbackData data = getRollbackForId(rollback.getRollbackId());
         if (data == null) {
-            sendFailure(statusReceiver, "No rollback available for package.");
-            return;
-        }
-
-        if (data.rollbackId != rollback.getRollbackId()) {
-            sendFailure(statusReceiver, "Rollback for package is out of date.");
+            sendFailure(statusReceiver, "Rollback unavailable");
             return;
         }
 
@@ -335,14 +297,8 @@
         PackageManager pm = context.getPackageManager();
         try {
             PackageInstaller packageInstaller = pm.getPackageInstaller();
-            String installerPackageName = pm.getInstallerPackageName(targetPackageName);
-            if (installerPackageName == null) {
-                sendFailure(statusReceiver, "Cannot find installer package");
-                return;
-            }
             PackageInstaller.SessionParams parentParams = new PackageInstaller.SessionParams(
                     PackageInstaller.SessionParams.MODE_FULL_INSTALL);
-            parentParams.setInstallerPackageName(installerPackageName);
             parentParams.setAllowDowngrade(true);
             parentParams.setMultiPackage();
             int parentSessionId = packageInstaller.createSession(parentParams);
@@ -351,6 +307,11 @@
             for (PackageRollbackInfo info : data.packages) {
                 PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                         PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+                String installerPackageName = pm.getInstallerPackageName(info.getPackageName());
+                if (installerPackageName == null) {
+                    sendFailure(statusReceiver, "Cannot find installer package");
+                    return;
+                }
                 params.setInstallerPackageName(installerPackageName);
                 params.setAllowDowngrade(true);
                 int sessionId = packageInstaller.createSession(params);
@@ -392,7 +353,7 @@
                             addRecentlyExecutedRollback(rollback);
                             sendSuccess(statusReceiver);
 
-                            Intent broadcast = new Intent(Intent.ACTION_PACKAGE_ROLLBACK_EXECUTED);
+                            Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED);
 
                             // TODO: This call emits the warning "Calling a method in the
                             // system process without a qualified user". Fix that.
@@ -406,7 +367,7 @@
             data.inProgress = true;
             parentSession.commit(receiver.getIntentSender());
         } catch (IOException e) {
-            Log.e(TAG, "Unable to roll back " + targetPackageName, e);
+            Log.e(TAG, "Rollback failed", e);
             sendFailure(statusReceiver, "IOException: " + e.toString());
             return;
         }
@@ -537,9 +498,12 @@
             boolean changed = false;
             while (iter.hasNext()) {
                 RollbackInfo rollback = iter.next();
-                if (packageName.equals(rollback.targetPackage.getPackageName())) {
-                    iter.remove();
-                    changed = true;
+                for (PackageRollbackInfo info : rollback.getPackages()) {
+                    if (packageName.equals(info.getPackageName())) {
+                        iter.remove();
+                        changed = true;
+                        break;
+                    }
                 }
             }
 
@@ -935,6 +899,25 @@
         return null;
     }
 
+    /*
+     * Returns the RollbackData, if any, for an available rollback with the
+     * given rollbackId.
+     */
+    private RollbackData getRollbackForId(int rollbackId) {
+        synchronized (mLock) {
+            // TODO: Have ensureRollbackDataLoadedLocked return the list of
+            // available rollbacks, to hopefully avoid forgetting to call it?
+            ensureRollbackDataLoadedLocked();
+            for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
+                RollbackData data = mAvailableRollbacks.get(i);
+                if (data.rollbackId == rollbackId) {
+                    return data;
+                }
+            }
+        }
+        return null;
+    }
+
     @GuardedBy("mLock")
     private int allocateRollbackIdLocked() throws IOException {
         int n = 0;
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 1f2f1cc..3954a11 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInstaller;
+import android.content.rollback.PackageRollbackInfo;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
 import android.os.Handler;
@@ -51,11 +52,14 @@
     @Override
     public boolean onHealthCheckFailed(String packageName) {
         RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
-        RollbackInfo rollback = rollbackManager.getAvailableRollback(packageName);
-        if (rollback != null) {
-            // TODO(zezeozue): Only rollback if rollback version == failed package version
-            mHandler.post(() -> executeRollback(rollbackManager, rollback));
-            return true;
+        for (RollbackInfo rollback : rollbackManager.getAvailableRollbacks()) {
+            for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
+                if (packageName.equals(packageRollback.getPackageName())) {
+                    // TODO(zezeozue): Only rollback if rollback version == failed package version
+                    mHandler.post(() -> executeRollback(rollbackManager, rollback));
+                    return true;
+                }
+            }
         }
         // Don't handle the notification, no rollbacks available
         return false;
@@ -84,7 +88,7 @@
                 }
             });
         });
-        manager.executeRollback(rollback, rollbackReceiver.getIntentSender());
+        manager.commitRollback(rollback, rollbackReceiver.getIntentSender());
     }
 
     @Override
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 7738be9..3b24b3e 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -114,13 +114,9 @@
                 for (int i = 0; i < array.length(); ++i) {
                     JSONObject element = array.getJSONObject(i);
                     int rollbackId = element.getInt("rollbackId");
-                    String packageName = element.getString("packageName");
-                    long higherVersionCode = element.getLong("higherVersionCode");
-                    long lowerVersionCode = element.getLong("lowerVersionCode");
-                    PackageRollbackInfo target = new PackageRollbackInfo(
-                            new VersionedPackage(packageName, higherVersionCode),
-                            new VersionedPackage(packageName, lowerVersionCode));
-                    RollbackInfo rollback = new RollbackInfo(rollbackId, target);
+                    List<PackageRollbackInfo> packages = packageRollbackInfosFromJson(
+                            element.getJSONArray("packages"));
+                    RollbackInfo rollback = new RollbackInfo(rollbackId, packages);
                     recentlyExecutedRollbacks.add(rollback);
                 }
             } catch (IOException | JSONException e) {
@@ -155,18 +151,8 @@
     void saveAvailableRollback(RollbackData data) throws IOException {
         try {
             JSONObject dataJson = new JSONObject();
-            JSONArray packagesJson = new JSONArray();
-            for (PackageRollbackInfo info : data.packages) {
-                JSONObject infoJson = new JSONObject();
-                infoJson.put("packageName", info.getPackageName());
-                infoJson.put("higherVersionCode",
-                        info.getVersionRolledBackFrom().getLongVersionCode());
-                infoJson.put("lowerVersionCode",
-                        info.getVersionRolledBackTo().getVersionCode());
-                packagesJson.put(infoJson);
-            }
             dataJson.put("rollbackId", data.rollbackId);
-            dataJson.put("packages", packagesJson);
+            dataJson.put("packages", toJson(data.packages));
             dataJson.put("timestamp", data.timestamp.toString());
 
             PrintWriter pw = new PrintWriter(new File(data.backupDir, "rollback.json"));
@@ -200,11 +186,7 @@
                 RollbackInfo rollback = recentlyExecutedRollbacks.get(i);
                 JSONObject element = new JSONObject();
                 element.put("rollbackId", rollback.getRollbackId());
-                element.put("packageName", rollback.targetPackage.getPackageName());
-                element.put("higherVersionCode",
-                        rollback.targetPackage.getVersionRolledBackFrom().getLongVersionCode());
-                element.put("lowerVersionCode",
-                        rollback.targetPackage.getVersionRolledBackTo().getLongVersionCode());
+                element.put("packages", toJson(rollback.getPackages()));
                 array.put(element);
             }
 
@@ -229,18 +211,7 @@
 
             int rollbackId = dataJson.getInt("rollbackId");
             RollbackData data = new RollbackData(rollbackId, backupDir);
-
-            JSONArray packagesJson = dataJson.getJSONArray("packages");
-            for (int i = 0; i < packagesJson.length(); ++i) {
-                JSONObject infoJson = packagesJson.getJSONObject(i);
-                String packageName = infoJson.getString("packageName");
-                long higherVersionCode = infoJson.getLong("higherVersionCode");
-                long lowerVersionCode = infoJson.getLong("lowerVersionCode");
-                data.packages.add(new PackageRollbackInfo(
-                        new VersionedPackage(packageName, higherVersionCode),
-                        new VersionedPackage(packageName, lowerVersionCode)));
-            }
-
+            data.packages.addAll(packageRollbackInfosFromJson(dataJson.getJSONArray("packages")));
             data.timestamp = Instant.parse(dataJson.getString("timestamp"));
             return data;
         } catch (JSONException | DateTimeParseException e) {
@@ -248,6 +219,40 @@
         }
     }
 
+    private JSONObject toJson(PackageRollbackInfo info) throws JSONException {
+        JSONObject json = new JSONObject();
+        json.put("packageName", info.getPackageName());
+        json.put("higherVersionCode", info.getVersionRolledBackFrom().getLongVersionCode());
+        json.put("lowerVersionCode", info.getVersionRolledBackTo().getLongVersionCode());
+        return json;
+    }
+
+    private PackageRollbackInfo packageRollbackInfoFromJson(JSONObject json) throws JSONException {
+        String packageName = json.getString("packageName");
+        long higherVersionCode = json.getLong("higherVersionCode");
+        long lowerVersionCode = json.getLong("lowerVersionCode");
+        return new PackageRollbackInfo(
+                new VersionedPackage(packageName, higherVersionCode),
+                new VersionedPackage(packageName, lowerVersionCode));
+    }
+
+    private JSONArray toJson(List<PackageRollbackInfo> infos) throws JSONException {
+        JSONArray json = new JSONArray();
+        for (PackageRollbackInfo info : infos) {
+            json.put(toJson(info));
+        }
+        return json;
+    }
+
+    private List<PackageRollbackInfo> packageRollbackInfosFromJson(JSONArray json)
+            throws JSONException {
+        List<PackageRollbackInfo> infos = new ArrayList<>();
+        for (int i = 0; i < json.length(); ++i) {
+            infos.add(packageRollbackInfoFromJson(json.getJSONObject(i)));
+        }
+        return infos;
+    }
+
     /**
      * Deletes a file completely.
      * If the file is a directory, its contents are deleted as well.
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
index 030641b..e10f866 100644
--- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
+++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
@@ -29,7 +29,7 @@
 
 /**
  * A broadcast receiver that can be used to get
- * ACTION_PACKAGE_ROLLBACK_EXECUTED broadcasts.
+ * ACTION_ROLLBACK_COMMITTED broadcasts.
  */
 class RollbackBroadcastReceiver extends BroadcastReceiver {
 
@@ -43,7 +43,7 @@
      */
     RollbackBroadcastReceiver() {
         IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_PACKAGE_ROLLBACK_EXECUTED);
+        filter.addAction(Intent.ACTION_ROLLBACK_COMMITTED);
         InstrumentationRegistry.getContext().registerReceiver(this, filter);
     }
 
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 13ac4f0..7ab716f 100644
--- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -31,11 +31,8 @@
 import android.util.Log;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import org.junit.Ignore;
@@ -43,6 +40,7 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -86,8 +84,8 @@
                     Manifest.permission.DELETE_PACKAGES,
                     Manifest.permission.MANAGE_ROLLBACKS);
 
-            // Register a broadcast receiver for notification when the rollback is
-            // done executing.
+            // Register a broadcast receiver for notification when the
+            // rollback has been committed.
             RollbackBroadcastReceiver broadcastReceiver = new RollbackBroadcastReceiver();
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
 
@@ -99,12 +97,11 @@
             // uninstalled and when rollback manager deletes the rollback. Fix it
             // so that's not the case!
             for (int i = 0; i < 5; ++i) {
-                for (RollbackInfo info : rm.getRecentlyExecutedRollbacks()) {
-                    if (TEST_APP_A.equals(info.targetPackage.getPackageName())) {
-                        Log.i(TAG, "Sleeping 1 second to wait for uninstall to take effect.");
-                        Thread.sleep(1000);
-                        break;
-                    }
+                RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+                        rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
+                if (rollback != null) {
+                    Log.i(TAG, "Sleeping 1 second to wait for uninstall to take effect.");
+                    Thread.sleep(1000);
                 }
             }
 
@@ -113,13 +110,11 @@
             // between when the app is uninstalled and when the previously
             // available rollback, if any, is removed.
             Thread.sleep(1000);
-            assertNull(rm.getAvailableRollback(TEST_APP_A));
-            assertFalse(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
+            assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A));
 
-            // There should be no recently executed rollbacks for this package.
-            for (RollbackInfo info : rm.getRecentlyExecutedRollbacks()) {
-                assertNotEquals(TEST_APP_A, info.targetPackage.getPackageName());
-            }
+            // There should be no recently committed rollbacks for this package.
+            assertNull(getUniqueRollbackInfoForPackage(
+                        rm.getRecentlyCommittedRollbacks(), TEST_APP_A));
 
             // Install v1 of the app (without rollbacks enabled).
             RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
@@ -134,10 +129,9 @@
             // between when the app is installed and when the rollback
             // is made available.
             Thread.sleep(1000);
-            assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
-            RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A);
-            assertNotNull(rollback);
-            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage);
+            RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
 
             // We should not have received any rollback requests yet.
             // TODO: Possibly flaky if, by chance, some other app on device
@@ -156,15 +150,9 @@
             assertNull(broadcastReceiver.poll(0, TimeUnit.SECONDS));
 
             // Verify the recent rollback has been recorded.
-            rollback = null;
-            for (RollbackInfo r : rm.getRecentlyExecutedRollbacks()) {
-                if (TEST_APP_A.equals(r.targetPackage.getPackageName())) {
-                    assertNull(rollback);
-                    rollback = r;
-                }
-            }
-            assertNotNull(rollback);
-            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage);
+            rollback = getUniqueRollbackInfoForPackage(
+                    rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
 
             broadcastReceiver.unregister();
             context.unregisterReceiver(enableRollbackReceiver);
@@ -202,28 +190,25 @@
             // is made available.
             Thread.sleep(1000);
 
-            assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
-            RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A);
-            assertNotNull(rollbackA);
-            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage);
+            RollbackInfo rollbackA = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA);
 
-            assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
-            RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B);
-            assertNotNull(rollbackB);
-            assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB.targetPackage);
+            RollbackInfo rollbackB = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_B);
+            assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB);
 
             // Reload the persisted data.
             rm.reloadPersistedData();
 
             // The apps should still be available for rollback.
-            rollbackA = rm.getAvailableRollback(TEST_APP_A);
-            assertNotNull(rollbackA);
-            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage);
+            rollbackA = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA);
 
-            assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
-            rollbackB = rm.getAvailableRollback(TEST_APP_B);
-            assertNotNull(rollbackB);
-            assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB.targetPackage);
+            rollbackB = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_B);
+            assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB);
 
             // Rollback of B should not rollback A
             RollbackTestUtils.rollback(rollbackB);
@@ -264,28 +249,23 @@
             // is made available.
             Thread.sleep(1000);
 
-            assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
-            RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A);
-            assertNotNull(rollbackA);
-            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage);
+            RollbackInfo rollbackA = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
+            assertRollbackInfoForAandB(rollbackA);
 
-            assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
-            RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B);
-            assertNotNull(rollbackB);
-            assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB.targetPackage);
+            RollbackInfo rollbackB = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_B);
+            assertRollbackInfoForAandB(rollbackB);
 
             // Reload the persisted data.
             rm.reloadPersistedData();
 
             // The apps should still be available for rollback.
-            rollbackA = rm.getAvailableRollback(TEST_APP_A);
-            assertNotNull(rollbackA);
-            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage);
+            rollbackA = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A);
+            assertRollbackInfoForAandB(rollbackA);
 
-            assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
-            rollbackB = rm.getAvailableRollback(TEST_APP_B);
-            assertNotNull(rollbackB);
-            assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB.targetPackage);
+            rollbackB = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_B);
+            assertRollbackInfoForAandB(rollbackB);
 
             // Rollback of B should rollback A as well
             RollbackTestUtils.rollback(rollbackB);
@@ -297,10 +277,10 @@
     }
 
     /**
-     * Test that recently executed rollback data is properly persisted.
+     * Test that recently committed rollback data is properly persisted.
      */
     @Test
-    public void testRecentlyExecutedRollbackPersistence() throws Exception {
+    public void testRecentlyCommittedRollbackPersistence() throws Exception {
         try {
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
@@ -319,37 +299,27 @@
             // between when the app is installed and when the rollback
             // is made available.
             Thread.sleep(1000);
-            assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
-            RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A);
+            RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
 
             // Roll back the app.
             RollbackTestUtils.rollback(rollback);
             assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
 
             // Verify the recent rollback has been recorded.
-            rollback = null;
-            for (RollbackInfo r : rm.getRecentlyExecutedRollbacks()) {
-                if (TEST_APP_A.equals(r.targetPackage.getPackageName())) {
-                    assertNull(rollback);
-                    rollback = r;
-                }
-            }
+            rollback = getUniqueRollbackInfoForPackage(
+                    rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
             assertNotNull(rollback);
-            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
 
             // Reload the persisted data.
             rm.reloadPersistedData();
 
             // Verify the recent rollback is still recorded.
-            rollback = null;
-            for (RollbackInfo r : rm.getRecentlyExecutedRollbacks()) {
-                if (TEST_APP_A.equals(r.targetPackage.getPackageName())) {
-                    assertNull(rollback);
-                    rollback = r;
-                }
-            }
+            rollback = getUniqueRollbackInfoForPackage(
+                    rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
             assertNotNull(rollback);
-            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
         } finally {
             RollbackTestUtils.dropShellPermissionIdentity();
         }
@@ -378,17 +348,16 @@
             // between when the app is installed and when the rollback
             // is made available.
             Thread.sleep(1000);
-            assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
-            RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A);
-            assertNotNull(rollback);
-            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage);
+            RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
 
             // Expire the rollback.
             rm.expireRollbackForPackage(TEST_APP_A);
 
             // The rollback should no longer be available.
-            assertNull(rm.getAvailableRollback(TEST_APP_A));
-            assertFalse(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
+            assertNull(getUniqueRollbackInfoForPackage(
+                        rm.getAvailableRollbacks(), TEST_APP_A));
         } finally {
             RollbackTestUtils.dropShellPermissionIdentity();
         }
@@ -459,7 +428,8 @@
             processUserData(TEST_APP_A);
 
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
-            RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A);
+            RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
             RollbackTestUtils.rollback(rollback);
             processUserData(TEST_APP_A);
         } finally {
@@ -469,12 +439,12 @@
 
     /**
      * Test restrictions on rollback broadcast sender.
-     * A random app should not be able to send a PACKAGE_ROLLBACK_EXECUTED broadcast.
+     * A random app should not be able to send a ROLLBACK_COMMITTED broadcast.
      */
     @Test
     public void testRollbackBroadcastRestrictions() throws Exception {
         RollbackBroadcastReceiver broadcastReceiver = new RollbackBroadcastReceiver();
-        Intent broadcast = new Intent(Intent.ACTION_PACKAGE_ROLLBACK_EXECUTED);
+        Intent broadcast = new Intent(Intent.ACTION_ROLLBACK_COMMITTED);
         try {
             InstrumentationRegistry.getContext().sendBroadcast(broadcast);
             fail("Succeeded in sending restricted broadcast from app context.");
@@ -516,18 +486,18 @@
             assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
 
             // Both test apps should now be available for rollback, and the
-            // targetPackage returned for rollback should be correct.
+            // RollbackInfo returned for the rollbacks should be correct.
             // TODO: See if there is a way to remove this race condition
             // between when the app is installed and when the rollback
             // is made available.
             Thread.sleep(1000);
-            RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A);
-            assertNotNull(rollbackA);
-            assertEquals(TEST_APP_A, rollbackA.targetPackage.getPackageName());
+            RollbackInfo rollbackA = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA);
 
-            RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B);
-            assertNotNull(rollbackB);
-            assertEquals(TEST_APP_B, rollbackB.targetPackage.getPackageName());
+            RollbackInfo rollbackB = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_B);
+            assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB);
 
             // Executing rollback should roll back the correct package.
             RollbackTestUtils.rollback(rollbackA);
@@ -558,21 +528,14 @@
         RollbackManager rm = RollbackTestUtils.getRollbackManager();
 
         try {
-            rm.getAvailableRollback(TEST_APP_A);
+            rm.getAvailableRollbacks();
             fail("expected SecurityException");
         } catch (SecurityException e) {
             // Expected.
         }
 
         try {
-            rm.getPackagesWithAvailableRollbacks();
-            fail("expected SecurityException");
-        } catch (SecurityException e) {
-            // Expected.
-        }
-
-        try {
-            rm.getRecentlyExecutedRollbacks();
+            rm.getRecentlyCommittedRollbacks();
             fail("expected SecurityException");
         } catch (SecurityException e) {
             // Expected.
@@ -581,7 +544,7 @@
         try {
             // TODO: What if the implementation checks arguments for non-null
             // first? Then this test isn't valid.
-            rm.executeRollback(null, null);
+            rm.commitRollback(null, null);
             fail("expected SecurityException");
         } catch (SecurityException e) {
             // Expected.
@@ -629,12 +592,9 @@
             assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
 
             // TEST_APP_A should now be available for rollback.
-            assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
-            RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A);
-            assertNotNull(rollback);
-
-            // TODO: Test the dependent apps for rollback are correct once we
-            // support that in the RollbackInfo API.
+            RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
+            assertRollbackInfoForAandB(rollback);
 
             // Rollback the app. It should cause both test apps to be rolled
             // back.
@@ -642,14 +602,16 @@
             assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
             assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
 
-            // We should not see a recent rollback listed for TEST_APP_B
-            for (RollbackInfo r : rm.getRecentlyExecutedRollbacks()) {
-                assertNotEquals(TEST_APP_B, r.targetPackage.getPackageName());
-            }
+            // We should see recent rollbacks listed for both A and B.
+            Thread.sleep(1000);
+            RollbackInfo rollbackA = getUniqueRollbackInfoForPackage(
+                    rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
 
-            // TODO: Test the listed dependent apps for the recently executed
-            // rollback are correct once we support that in the RollbackInfo
-            // API.
+            RollbackInfo rollbackB = getUniqueRollbackInfoForPackage(
+                    rm.getRecentlyCommittedRollbacks(), TEST_APP_B);
+            assertRollbackInfoForAandB(rollbackB);
+
+            assertEquals(rollbackA.getRollbackId(), rollbackB.getRollbackId());
         } finally {
             RollbackTestUtils.dropShellPermissionIdentity();
         }
@@ -697,13 +659,13 @@
             // between when the app is installed and when the rollback
             // is made available.
             Thread.sleep(1000);
-            RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A);
-            assertNotNull(rollbackA);
-            assertEquals(TEST_APP_A, rollbackA.targetPackage.getPackageName());
+            RollbackInfo rollbackA = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA);
 
-            RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B);
-            assertNotNull(rollbackB);
-            assertEquals(TEST_APP_B, rollbackB.targetPackage.getPackageName());
+            RollbackInfo rollbackB = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_B);
+            assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB);
 
             // Start apps PackageWatchdog#TRIGGER_FAILURE_COUNT times so TEST_APP_A crashes
             for (int i = 0; i < 5; i++) {
@@ -724,4 +686,47 @@
             RollbackTestUtils.dropShellPermissionIdentity();
         }
     }
+
+    // Helper function to test the value of a RollbackInfo with single package
+    private void assertRollbackInfoEquals(String packageName,
+            long versionRolledBackFrom, long versionRolledBackTo,
+            RollbackInfo info) {
+        assertNotNull(info);
+        assertEquals(1, info.getPackages().size());
+        assertPackageRollbackInfoEquals(packageName, versionRolledBackFrom, versionRolledBackTo,
+                info.getPackages().get(0));
+    }
+
+    // Helper function to test that the given rollback info is a rollback for
+    // the atomic set {A2, B2} -> {A1, B1}.
+    private void assertRollbackInfoForAandB(RollbackInfo rollback) {
+        assertNotNull(rollback);
+        assertEquals(2, rollback.getPackages().size());
+        if (TEST_APP_A.equals(rollback.getPackages().get(0).getPackageName())) {
+            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.getPackages().get(0));
+            assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollback.getPackages().get(1));
+        } else {
+            assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollback.getPackages().get(0));
+            assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.getPackages().get(1));
+        }
+    }
+
+    // Helper function to return the RollbackInfo with a given package in the
+    // list of rollbacks. Throws an assertion failure if there is more than
+    // one such rollback info. Returns null if there are no such rollback
+    // infos.
+    private RollbackInfo getUniqueRollbackInfoForPackage(List<RollbackInfo> rollbacks,
+            String packageName) {
+        RollbackInfo found = null;
+        for (RollbackInfo rollback : rollbacks) {
+            for (PackageRollbackInfo info : rollback.getPackages()) {
+                if (packageName.equals(info.getPackageName())) {
+                    assertNull(found);
+                    found = rollback;
+                    break;
+                }
+            }
+        }
+        return found;
+    }
 }
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
index edb1355..f481897 100644
--- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -90,12 +90,12 @@
     }
 
     /**
-     * Execute the given rollback.
+     * Commit the given rollback.
      * @throws AssertionError if the rollback fails.
      */
     static void rollback(RollbackInfo rollback) throws InterruptedException {
         RollbackManager rm = getRollbackManager();
-        rm.executeRollback(rollback, LocalIntentSender.getIntentSender());
+        rm.commitRollback(rollback, LocalIntentSender.getIntentSender());
         assertStatusSuccess(LocalIntentSender.getIntentSenderResult());
     }