diff options
| author | 2019-01-26 07:31:28 +0000 | |
|---|---|---|
| committer | 2019-01-26 07:31:28 +0000 | |
| commit | efb4132ba31d715a2b0a4830d764b5288c8bf3c8 (patch) | |
| tree | a482f5c2bd86977ac0344d774c130d2f11bbe894 | |
| parent | 71ae5ba4c91382851cf7d4bdbf58224592250c8f (diff) | |
| parent | 4b092ef6f75a8c8137bf37ab1c0905faf58da31a (diff) | |
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.
12 files changed, 266 insertions, 302 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index be07151a5cc8..31e6c6c04386 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1303,13 +1303,13 @@ package android.content { 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 @@ package android.content.rollback { 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 9e7aaf652a4d..22f73dbd4644 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2375,8 +2375,7 @@ public class Intent implements Parcelable, Cloneable { 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 @@ public class Intent implements Parcelable, Cloneable { */ @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 420bcb69e0c4..63d75a097d24 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 0803a7c1d651..8532b5a4844e 100644 --- a/core/java/android/content/rollback/RollbackInfo.java +++ b/core/java/android/content/rollback/RollbackInfo.java @@ -20,6 +20,8 @@ import android.annotation.SystemApi; 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 @@ public final class RollbackInfo implements Parcelable { */ 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 @@ public final class RollbackInfo implements Parcelable { 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 @@ public final class RollbackInfo implements Parcelable { @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 c1c0bc1d3e07..2566ac562e11 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 @@ public final class RollbackManager { } /** - * 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 @@ public final class RollbackManager { * (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 @@ public final class RollbackManager { } /** - * 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 4a54bd775387..893a6079acca 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 8b4c410000bb..6487bd7af7ee 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.PackageManager; 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.Instant; 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 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } @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 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { */ 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 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { 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 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { 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 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { 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 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { 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 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { 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 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { 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 1f2f1ccd7383..3954a1178e09 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 @@ package com.android.server.rollback; 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 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve @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 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve } }); }); - 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 7738be9d32bb..3b24b3e9a444 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 @@ class RollbackStore { 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 @@ class RollbackStore { 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 @@ class RollbackStore { 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 @@ class RollbackStore { 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 @@ class RollbackStore { } } + 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 030641bf0895..e10f866c899f 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 @@ import java.util.concurrent.TimeUnit; /** * 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 @@ class RollbackBroadcastReceiver extends BroadcastReceiver { */ 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 13ac4f09dd86..7ab716fac6df 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.support.test.InstrumentationRegistry; 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.Test; 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 @@ public class RollbackTest { 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 @@ public class RollbackTest { // 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 @@ public class RollbackTest { // 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 @@ public class RollbackTest { // 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 @@ public class RollbackTest { 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 @@ public class RollbackTest { // 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 @@ public class RollbackTest { // 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 @@ public class RollbackTest { } /** - * 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 @@ public class RollbackTest { // 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 @@ public class RollbackTest { // 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 @@ public class RollbackTest { 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 @@ public class RollbackTest { /** * 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 @@ public class RollbackTest { 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 @@ public class RollbackTest { RollbackManager rm = RollbackTestUtils.getRollbackManager(); try { - rm.getAvailableRollback(TEST_APP_A); - fail("expected SecurityException"); - } catch (SecurityException e) { - // Expected. - } - - try { - rm.getPackagesWithAvailableRollbacks(); + rm.getAvailableRollbacks(); fail("expected SecurityException"); } catch (SecurityException e) { // Expected. } try { - rm.getRecentlyExecutedRollbacks(); + rm.getRecentlyCommittedRollbacks(); fail("expected SecurityException"); } catch (SecurityException e) { // Expected. @@ -581,7 +544,7 @@ public class RollbackTest { 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 @@ public class RollbackTest { 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 @@ public class RollbackTest { 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 @@ public class RollbackTest { // 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 @@ public class RollbackTest { 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 edb13556b8fc..f481897c060c 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 @@ class RollbackTestUtils { } /** - * 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()); } |