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());
}