summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/system-current.txt13
-rw-r--r--core/java/android/content/Intent.java1
-rw-r--r--core/java/android/content/rollback/PackageRollbackInfo.java68
-rw-r--r--core/java/android/content/rollback/RollbackInfo.java19
-rw-r--r--services/core/java/com/android/server/rollback/RollbackData.java8
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java108
-rw-r--r--services/core/java/com/android/server/rollback/RollbackStore.java48
-rw-r--r--tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java1
-rw-r--r--tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java85
9 files changed, 184 insertions, 167 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index 69dc6086f1f7..0d7465c9fed3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1672,22 +1672,17 @@ package android.content.pm.permission {
package android.content.rollback {
public final class PackageRollbackInfo implements android.os.Parcelable {
- ctor public PackageRollbackInfo(String, android.content.rollback.PackageRollbackInfo.PackageVersion, android.content.rollback.PackageRollbackInfo.PackageVersion);
method public int describeContents();
+ method public String getPackageName();
+ method public android.content.pm.VersionedPackage getVersionRolledBackFrom();
+ method public android.content.pm.VersionedPackage getVersionRolledBackTo();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.rollback.PackageRollbackInfo> CREATOR;
- field public final android.content.rollback.PackageRollbackInfo.PackageVersion higherVersion;
- field public final android.content.rollback.PackageRollbackInfo.PackageVersion lowerVersion;
- field public final String packageName;
- }
-
- public static class PackageRollbackInfo.PackageVersion {
- ctor public PackageRollbackInfo.PackageVersion(long);
- field public final long versionCode;
}
public final class RollbackInfo implements android.os.Parcelable {
method public int describeContents();
+ 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;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a6b47ff1320d..b46203c7a682 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2377,7 +2377,6 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast Action: An existing version of an application package has been
* rolled back to a previous version.
- * The data contains the name of the package.
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 204002426d17..4644a83de462 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -17,11 +17,10 @@
package android.content.rollback;
import android.annotation.SystemApi;
+import android.content.pm.VersionedPackage;
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Objects;
-
/**
* Information about a rollback available for a particular package.
*
@@ -29,59 +28,41 @@ import java.util.Objects;
*/
@SystemApi
public final class PackageRollbackInfo implements Parcelable {
- /**
- * The name of a package being rolled back.
- */
- public final String packageName;
+
+ private final VersionedPackage mVersionRolledBackFrom;
+ private final VersionedPackage mVersionRolledBackTo;
/**
- * The version the package was rolled back from.
+ * Returns the name of the package to roll back from.
*/
- public final PackageVersion higherVersion;
+ public String getPackageName() {
+ return mVersionRolledBackFrom.getPackageName();
+ }
/**
- * The version the package was rolled back to.
+ * Returns the version of the package rolled back from.
*/
- public final PackageVersion lowerVersion;
+ public VersionedPackage getVersionRolledBackFrom() {
+ return mVersionRolledBackFrom;
+ }
/**
- * Represents a version of a package.
+ * Returns the version of the package rolled back to.
*/
- public static class PackageVersion {
- public final long versionCode;
-
- // TODO(b/120200473): Include apk sha or some other way to distinguish
- // between two different apks with the same version code.
- public PackageVersion(long versionCode) {
- this.versionCode = versionCode;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof PackageVersion) {
- PackageVersion otherVersion = (PackageVersion) other;
- return versionCode == otherVersion.versionCode;
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(versionCode);
- }
+ public VersionedPackage getVersionRolledBackTo() {
+ return mVersionRolledBackTo;
}
- public PackageRollbackInfo(String packageName,
- PackageVersion higherVersion, PackageVersion lowerVersion) {
- this.packageName = packageName;
- this.higherVersion = higherVersion;
- this.lowerVersion = lowerVersion;
+ /** @hide */
+ public PackageRollbackInfo(VersionedPackage packageRolledBackFrom,
+ VersionedPackage packageRolledBackTo) {
+ this.mVersionRolledBackFrom = packageRolledBackFrom;
+ this.mVersionRolledBackTo = packageRolledBackTo;
}
private PackageRollbackInfo(Parcel in) {
- this.packageName = in.readString();
- this.higherVersion = new PackageVersion(in.readLong());
- this.lowerVersion = new PackageVersion(in.readLong());
+ this.mVersionRolledBackFrom = VersionedPackage.CREATOR.createFromParcel(in);
+ this.mVersionRolledBackTo = VersionedPackage.CREATOR.createFromParcel(in);
}
@Override
@@ -91,9 +72,8 @@ public final class PackageRollbackInfo implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
- out.writeString(packageName);
- out.writeLong(higherVersion.versionCode);
- out.writeLong(lowerVersion.versionCode);
+ mVersionRolledBackFrom.writeToParcel(out, flags);
+ mVersionRolledBackTo.writeToParcel(out, flags);
}
public static final Parcelable.Creator<PackageRollbackInfo> CREATOR =
diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java
index 66df4fea3f23..0803a7c1d651 100644
--- a/core/java/android/content/rollback/RollbackInfo.java
+++ b/core/java/android/content/rollback/RollbackInfo.java
@@ -30,6 +30,11 @@ import android.os.Parcelable;
public final class RollbackInfo implements Parcelable {
/**
+ * A unique identifier for the rollback.
+ */
+ private final int mRollbackId;
+
+ /**
* The package that needs to be rolled back.
*/
public final PackageRollbackInfo targetPackage;
@@ -40,12 +45,21 @@ public final class RollbackInfo implements Parcelable {
// staged installs is supported.
/** @hide */
- public RollbackInfo(PackageRollbackInfo targetPackage) {
+ public RollbackInfo(int rollbackId, PackageRollbackInfo targetPackage) {
+ this.mRollbackId = rollbackId;
this.targetPackage = targetPackage;
}
private RollbackInfo(Parcel in) {
- this.targetPackage = PackageRollbackInfo.CREATOR.createFromParcel(in);
+ mRollbackId = in.readInt();
+ targetPackage = PackageRollbackInfo.CREATOR.createFromParcel(in);
+ }
+
+ /**
+ * Returns a unique identifier for this rollback.
+ */
+ public int getRollbackId() {
+ return mRollbackId;
}
@Override
@@ -55,6 +69,7 @@ public final class RollbackInfo implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mRollbackId);
targetPackage.writeToParcel(out, flags);
}
diff --git a/services/core/java/com/android/server/rollback/RollbackData.java b/services/core/java/com/android/server/rollback/RollbackData.java
index f0589aac8239..4015c4f7b391 100644
--- a/services/core/java/com/android/server/rollback/RollbackData.java
+++ b/services/core/java/com/android/server/rollback/RollbackData.java
@@ -29,6 +29,11 @@ import java.util.List;
*/
class RollbackData {
/**
+ * A unique identifier for this rollback.
+ */
+ public final int rollbackId;
+
+ /**
* The per-package rollback information.
*/
public final List<PackageRollbackInfo> packages = new ArrayList<>();
@@ -44,7 +49,8 @@ class RollbackData {
*/
public Instant timestamp;
- RollbackData(File backupDir) {
+ RollbackData(int rollbackId, File backupDir) {
+ this.rollbackId = rollbackId;
this.backupDir = backupDir;
}
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 085b4afac0e2..7f515bf63bc1 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -16,7 +16,6 @@
package com.android.server.rollback;
-import android.Manifest;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -32,10 +31,10 @@ 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;
import android.content.rollback.RollbackInfo;
-import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -46,6 +45,7 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.storage.StorageManager;
import android.util.Log;
+import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
@@ -55,14 +55,16 @@ import com.android.server.pm.PackageManagerServiceUtils;
import java.io.File;
import java.io.IOException;
+import java.security.SecureRandom;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Map;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Random;
import java.util.Set;
import java.util.function.Consumer;
@@ -82,6 +84,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// mLock is held when they are called.
private final Object mLock = new Object();
+ // Used for generating rollback IDs.
+ private final Random mRandom = new SecureRandom();
+
+ // Set of allocated rollback ids
+ @GuardedBy("mLock")
+ private final SparseBooleanArray mAllocatedRollbackIds = new SparseBooleanArray();
+
// Package rollback data for rollback-enabled installs that have not yet
// been committed. Maps from sessionId to rollback data.
@GuardedBy("mLock")
@@ -209,10 +218,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// it's out of date or not, so no need to check package versions here.
for (PackageRollbackInfo info : data.packages) {
- if (info.packageName.equals(packageName)) {
+ if (info.getPackageName().equals(packageName)) {
// TODO: Once the RollbackInfo API supports info about
// dependant packages, add that info here.
- return new RollbackInfo(info);
+ return new RollbackInfo(data.rollbackId, info);
}
}
return null;
@@ -230,7 +239,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
RollbackData data = mAvailableRollbacks.get(i);
for (PackageRollbackInfo info : data.packages) {
- packageNames.add(info.packageName);
+ packageNames.add(info.getPackageName());
}
}
}
@@ -272,7 +281,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
*/
private void executeRollbackInternal(RollbackInfo rollback,
String callerPackageName, IntentSender statusReceiver) {
- String targetPackageName = rollback.targetPackage.packageName;
+ String targetPackageName = rollback.targetPackage.getPackageName();
Log.i(TAG, "Initiating rollback of " + targetPackageName);
// Get the latest RollbackData for the target package.
@@ -282,15 +291,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
return;
}
- // Verify the latest rollback matches the version requested.
- // TODO: Check dependant packages too once RollbackInfo includes that
- // information.
- for (PackageRollbackInfo info : data.packages) {
- if (info.packageName.equals(targetPackageName)
- && !rollback.targetPackage.higherVersion.equals(info.higherVersion)) {
- sendFailure(statusReceiver, "Rollback is out of date.");
- return;
- }
+ if (data.rollbackId != rollback.getRollbackId()) {
+ sendFailure(statusReceiver, "Rollback for package is out of date");
+ return;
}
// Verify the RollbackData is up to date with what's installed on
@@ -302,15 +305,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// Figure out how to ensure we don't commit the rollback if
// roll forward happens at the same time.
for (PackageRollbackInfo info : data.packages) {
- PackageRollbackInfo.PackageVersion installedVersion =
- getInstalledPackageVersion(info.packageName);
+ VersionedPackage installedVersion = getInstalledPackageVersion(info.getPackageName());
if (installedVersion == null) {
// TODO: Test this case
sendFailure(statusReceiver, "Package to roll back is not installed");
return;
}
- if (!info.higherVersion.equals(installedVersion)) {
+ if (!packageVersionsEqual(info.getVersionRolledBackFrom(), installedVersion)) {
// TODO: Test this case
sendFailure(statusReceiver, "Package version to roll back not installed.");
return;
@@ -353,7 +355,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// TODO: Will it always be called "base.apk"? What about splits?
// What about apex?
- File packageDir = new File(data.backupDir, info.packageName);
+ File packageDir = new File(data.backupDir, info.getPackageName());
File baseApk = new File(packageDir, "base.apk");
try (ParcelFileDescriptor fd = ParcelFileDescriptor.open(baseApk,
ParcelFileDescriptor.MODE_READ_ONLY)) {
@@ -380,12 +382,12 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
addRecentlyExecutedRollback(rollback);
sendSuccess(statusReceiver);
- Intent broadcast = new Intent(Intent.ACTION_PACKAGE_ROLLBACK_EXECUTED,
- Uri.fromParts("package", targetPackageName,
- Manifest.permission.MANAGE_ROLLBACKS));
+ Intent broadcast = new Intent(Intent.ACTION_PACKAGE_ROLLBACK_EXECUTED);
// TODO: This call emits the warning "Calling a method in the
// system process without a qualified user". Fix that.
+ // TODO: Limit this to receivers holding the
+ // MANAGE_ROLLBACKS permission?
mContext.sendBroadcast(broadcast);
}
);
@@ -427,7 +429,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
while (iter.hasNext()) {
RollbackData data = iter.next();
for (PackageRollbackInfo info : data.packages) {
- if (info.packageName.equals(packageName)) {
+ if (info.getPackageName().equals(packageName)) {
iter.remove();
mRollbackStore.deleteAvailableRollback(data);
break;
@@ -469,7 +471,15 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
@GuardedBy("mLock")
private void loadAllRollbackDataLocked() {
mAvailableRollbacks = mRollbackStore.loadAvailableRollbacks();
+ for (RollbackData data : mAvailableRollbacks) {
+ mAllocatedRollbackIds.put(data.rollbackId, true);
+ }
+
mRecentlyExecutedRollbacks = mRollbackStore.loadRecentlyExecutedRollbacks();
+ for (RollbackInfo info : mRecentlyExecutedRollbacks) {
+ mAllocatedRollbackIds.put(info.getRollbackId(), true);
+ }
+
scheduleExpiration(0);
}
@@ -481,8 +491,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
private void onPackageReplaced(String packageName) {
// TODO: Could this end up incorrectly deleting a rollback for a
// package that is about to be installed?
- PackageRollbackInfo.PackageVersion installedVersion =
- getInstalledPackageVersion(packageName);
+ VersionedPackage installedVersion = getInstalledPackageVersion(packageName);
synchronized (mLock) {
ensureRollbackDataLoadedLocked();
@@ -490,8 +499,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
while (iter.hasNext()) {
RollbackData data = iter.next();
for (PackageRollbackInfo info : data.packages) {
- if (info.packageName.equals(packageName)
- && !info.higherVersion.equals(installedVersion)) {
+ if (info.getPackageName().equals(packageName)
+ && !packageVersionsEqual(
+ info.getVersionRolledBackFrom(),
+ installedVersion)) {
iter.remove();
mRollbackStore.deleteAvailableRollback(data);
break;
@@ -514,7 +525,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
boolean changed = false;
while (iter.hasNext()) {
RollbackInfo rollback = iter.next();
- if (packageName.equals(rollback.targetPackage.packageName)) {
+ if (packageName.equals(rollback.targetPackage.getPackageName())) {
iter.remove();
changed = true;
}
@@ -689,8 +700,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
return false;
}
- PackageRollbackInfo.PackageVersion newVersion =
- new PackageRollbackInfo.PackageVersion(newPackage.versionCode);
+ VersionedPackage newVersion = new VersionedPackage(packageName, newPackage.versionCode);
// Get information about the currently installed package.
PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
@@ -701,8 +711,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
Log.e(TAG, packageName + " is not installed");
return false;
}
- PackageRollbackInfo.PackageVersion installedVersion =
- new PackageRollbackInfo.PackageVersion(installedPackage.getLongVersionCode());
+ VersionedPackage installedVersion = new VersionedPackage(packageName,
+ installedPackage.getLongVersionCode());
for (int user : installedUsers) {
final int storageFlags;
@@ -723,8 +733,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
}
- PackageRollbackInfo info = new PackageRollbackInfo(
- packageName, newVersion, installedVersion);
+ PackageRollbackInfo info = new PackageRollbackInfo(newVersion, installedVersion);
RollbackData data;
try {
@@ -732,7 +741,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
mChildSessions.put(childSessionId, parentSessionId);
data = mPendingRollbacks.get(parentSessionId);
if (data == null) {
- data = mRollbackStore.createAvailableRollback();
+ int rollbackId = allocateRollbackIdLocked();
+ data = mRollbackStore.createAvailableRollback(rollbackId);
mPendingRollbacks.put(parentSessionId, data);
}
data.packages.add(info);
@@ -819,7 +829,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
* Gets the version of the package currently installed.
* Returns null if the package is not currently installed.
*/
- private PackageRollbackInfo.PackageVersion getInstalledPackageVersion(String packageName) {
+ private VersionedPackage getInstalledPackageVersion(String packageName) {
PackageManager pm = mContext.getPackageManager();
PackageInfo pkgInfo = null;
try {
@@ -828,7 +838,12 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
return null;
}
- return new PackageRollbackInfo.PackageVersion(pkgInfo.getLongVersionCode());
+ return new VersionedPackage(packageName, pkgInfo.getLongVersionCode());
+ }
+
+ private boolean packageVersionsEqual(VersionedPackage a, VersionedPackage b) {
+ return a.getPackageName().equals(b.getPackageName())
+ && a.getLongVersionCode() == b.getLongVersionCode();
}
private class SessionCallback extends PackageInstaller.SessionCallback {
@@ -904,7 +919,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
RollbackData data = mAvailableRollbacks.get(i);
for (PackageRollbackInfo info : data.packages) {
- if (info.packageName.equals(packageName)) {
+ if (info.getPackageName().equals(packageName)) {
return data;
}
}
@@ -912,4 +927,19 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
return null;
}
+
+ @GuardedBy("mLock")
+ private int allocateRollbackIdLocked() throws IOException {
+ int n = 0;
+ int rollbackId;
+ do {
+ rollbackId = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
+ if (!mAllocatedRollbackIds.get(rollbackId, false)) {
+ mAllocatedRollbackIds.put(rollbackId, true);
+ return rollbackId;
+ }
+ } while (n++ < 32);
+
+ throw new IOException("Failed to allocate rollback ID");
+ }
}
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index eb06bb24c24c..7738be9d32bb 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -16,6 +16,7 @@
package com.android.server.rollback;
+import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.RollbackInfo;
import android.util.Log;
@@ -29,7 +30,6 @@ import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
-import java.nio.file.Files;
import java.time.Instant;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
@@ -58,7 +58,7 @@ class RollbackStore {
// base.apk
// recently_executed.json
//
- // * XXX, YYY are random strings from Files.createTempDirectory
+ // * XXX, YYY are the rollbackIds for the corresponding rollbacks.
// * rollback.json contains all relevant metadata for the rollback. This
// file is not written until the rollback is made available.
//
@@ -113,13 +113,14 @@ class RollbackStore {
JSONArray array = object.getJSONArray("recentlyExecuted");
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(packageName,
- new PackageRollbackInfo.PackageVersion(higherVersionCode),
- new PackageRollbackInfo.PackageVersion(lowerVersionCode));
- RollbackInfo rollback = new RollbackInfo(target);
+ PackageRollbackInfo target = new PackageRollbackInfo(
+ new VersionedPackage(packageName, higherVersionCode),
+ new VersionedPackage(packageName, lowerVersionCode));
+ RollbackInfo rollback = new RollbackInfo(rollbackId, target);
recentlyExecutedRollbacks.add(rollback);
}
} catch (IOException | JSONException e) {
@@ -135,9 +136,9 @@ class RollbackStore {
/**
* Creates a new RollbackData instance with backupDir assigned.
*/
- RollbackData createAvailableRollback() throws IOException {
- File backupDir = Files.createTempDirectory(mAvailableRollbacksDir.toPath(), null).toFile();
- return new RollbackData(backupDir);
+ RollbackData createAvailableRollback(int rollbackId) throws IOException {
+ File backupDir = new File(mAvailableRollbacksDir, Integer.toString(rollbackId));
+ return new RollbackData(rollbackId, backupDir);
}
/**
@@ -157,11 +158,14 @@ class RollbackStore {
JSONArray packagesJson = new JSONArray();
for (PackageRollbackInfo info : data.packages) {
JSONObject infoJson = new JSONObject();
- infoJson.put("packageName", info.packageName);
- infoJson.put("higherVersionCode", info.higherVersion.versionCode);
- infoJson.put("lowerVersionCode", info.lowerVersion.versionCode);
+ 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("timestamp", data.timestamp.toString());
@@ -195,9 +199,12 @@ class RollbackStore {
for (int i = 0; i < recentlyExecutedRollbacks.size(); ++i) {
RollbackInfo rollback = recentlyExecutedRollbacks.get(i);
JSONObject element = new JSONObject();
- element.put("packageName", rollback.targetPackage.packageName);
- element.put("higherVersionCode", rollback.targetPackage.higherVersion.versionCode);
- element.put("lowerVersionCode", rollback.targetPackage.lowerVersion.versionCode);
+ 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());
array.put(element);
}
@@ -216,19 +223,22 @@ class RollbackStore {
*/
private RollbackData loadRollbackData(File backupDir) throws IOException {
try {
- RollbackData data = new RollbackData(backupDir);
File rollbackJsonFile = new File(backupDir, "rollback.json");
JSONObject dataJson = new JSONObject(
IoUtils.readFileAsString(rollbackJsonFile.getAbsolutePath()));
+
+ 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(packageName,
- new PackageRollbackInfo.PackageVersion(higherVersionCode),
- new PackageRollbackInfo.PackageVersion(lowerVersionCode)));
+ data.packages.add(new PackageRollbackInfo(
+ new VersionedPackage(packageName, higherVersionCode),
+ new VersionedPackage(packageName, lowerVersionCode)));
}
data.timestamp = Instant.parse(dataJson.getString("timestamp"));
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
index d3c39f0b8248..030641bf0895 100644
--- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
+++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
@@ -44,7 +44,6 @@ class RollbackBroadcastReceiver extends BroadcastReceiver {
RollbackBroadcastReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ROLLBACK_EXECUTED);
- filter.addDataScheme("package");
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 ec6f4b55d3ea..9d67cea05fc8 100644
--- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -22,9 +22,9 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
-import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.test.InstrumentationRegistry;
@@ -98,7 +98,7 @@ public class RollbackTest {
// 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.packageName)) {
+ 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;
@@ -116,7 +116,7 @@ public class RollbackTest {
// There should be no recently executed rollbacks for this package.
for (RollbackInfo info : rm.getRecentlyExecutedRollbacks()) {
- assertNotEquals(TEST_APP_A, info.targetPackage.packageName);
+ assertNotEquals(TEST_APP_A, info.targetPackage.getPackageName());
}
// Install v1 of the app (without rollbacks enabled).
@@ -135,9 +135,7 @@ public class RollbackTest {
assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A);
assertNotNull(rollback);
- assertEquals(TEST_APP_A, rollback.targetPackage.packageName);
- assertEquals(2, rollback.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollback.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage);
// We should not have received any rollback requests yet.
// TODO: Possibly flaky if, by chance, some other app on device
@@ -153,21 +151,18 @@ public class RollbackTest {
// received could lead to test flakiness.
Intent broadcast = broadcastReceiver.poll(5, TimeUnit.SECONDS);
assertNotNull(broadcast);
- assertEquals(TEST_APP_A, broadcast.getData().getSchemeSpecificPart());
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.packageName)) {
+ if (TEST_APP_A.equals(r.targetPackage.getPackageName())) {
assertNull(rollback);
rollback = r;
}
}
assertNotNull(rollback);
- assertEquals(TEST_APP_A, rollback.targetPackage.packageName);
- assertEquals(2, rollback.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollback.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage);
broadcastReceiver.unregister();
context.unregisterReceiver(enableRollbackReceiver);
@@ -208,16 +203,12 @@ public class RollbackTest {
assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A);
assertNotNull(rollbackA);
- assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName);
- assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage);
assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B);
assertNotNull(rollbackB);
- assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName);
- assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB.targetPackage);
// Reload the persisted data.
rm.reloadPersistedData();
@@ -225,16 +216,12 @@ public class RollbackTest {
// The apps should still be available for rollback.
rollbackA = rm.getAvailableRollback(TEST_APP_A);
assertNotNull(rollbackA);
- assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName);
- assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage);
assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
rollbackB = rm.getAvailableRollback(TEST_APP_B);
assertNotNull(rollbackB);
- assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName);
- assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB.targetPackage);
// Rollback of B should not rollback A
RollbackTestUtils.rollback(rollbackB);
@@ -278,16 +265,12 @@ public class RollbackTest {
assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A);
assertNotNull(rollbackA);
- assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName);
- assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage);
assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B);
assertNotNull(rollbackB);
- assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName);
- assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB.targetPackage);
// Reload the persisted data.
rm.reloadPersistedData();
@@ -295,16 +278,12 @@ public class RollbackTest {
// The apps should still be available for rollback.
rollbackA = rm.getAvailableRollback(TEST_APP_A);
assertNotNull(rollbackA);
- assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName);
- assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage);
assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B));
rollbackB = rm.getAvailableRollback(TEST_APP_B);
assertNotNull(rollbackB);
- assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName);
- assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB.targetPackage);
// Rollback of B should rollback A as well
RollbackTestUtils.rollback(rollbackB);
@@ -348,15 +327,13 @@ public class RollbackTest {
// Verify the recent rollback has been recorded.
rollback = null;
for (RollbackInfo r : rm.getRecentlyExecutedRollbacks()) {
- if (TEST_APP_A.equals(r.targetPackage.packageName)) {
+ if (TEST_APP_A.equals(r.targetPackage.getPackageName())) {
assertNull(rollback);
rollback = r;
}
}
assertNotNull(rollback);
- assertEquals(TEST_APP_A, rollback.targetPackage.packageName);
- assertEquals(2, rollback.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollback.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage);
// Reload the persisted data.
rm.reloadPersistedData();
@@ -364,15 +341,13 @@ public class RollbackTest {
// Verify the recent rollback is still recorded.
rollback = null;
for (RollbackInfo r : rm.getRecentlyExecutedRollbacks()) {
- if (TEST_APP_A.equals(r.targetPackage.packageName)) {
+ if (TEST_APP_A.equals(r.targetPackage.getPackageName())) {
assertNull(rollback);
rollback = r;
}
}
assertNotNull(rollback);
- assertEquals(TEST_APP_A, rollback.targetPackage.packageName);
- assertEquals(2, rollback.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollback.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage);
} finally {
RollbackTestUtils.dropShellPermissionIdentity();
}
@@ -404,9 +379,7 @@ public class RollbackTest {
assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A));
RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A);
assertNotNull(rollback);
- assertEquals(TEST_APP_A, rollback.targetPackage.packageName);
- assertEquals(2, rollback.targetPackage.higherVersion.versionCode);
- assertEquals(1, rollback.targetPackage.lowerVersion.versionCode);
+ assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage);
// Expire the rollback.
rm.expireRollbackForPackage(TEST_APP_A);
@@ -499,8 +472,7 @@ public class RollbackTest {
@Test
public void testRollbackBroadcastRestrictions() throws Exception {
RollbackBroadcastReceiver broadcastReceiver = new RollbackBroadcastReceiver();
- Intent broadcast = new Intent(Intent.ACTION_PACKAGE_ROLLBACK_EXECUTED,
- Uri.fromParts("package", "com.android.tests.rollback.bogus", null));
+ Intent broadcast = new Intent(Intent.ACTION_PACKAGE_ROLLBACK_EXECUTED);
try {
InstrumentationRegistry.getContext().sendBroadcast(broadcast);
fail("Succeeded in sending restricted broadcast from app context.");
@@ -549,11 +521,11 @@ public class RollbackTest {
Thread.sleep(1000);
RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A);
assertNotNull(rollbackA);
- assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName);
+ assertEquals(TEST_APP_A, rollbackA.targetPackage.getPackageName());
RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B);
assertNotNull(rollbackB);
- assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName);
+ assertEquals(TEST_APP_B, rollbackB.targetPackage.getPackageName());
// Executing rollback should roll back the correct package.
RollbackTestUtils.rollback(rollbackA);
@@ -670,7 +642,7 @@ public class RollbackTest {
// We should not see a recent rollback listed for TEST_APP_B
for (RollbackInfo r : rm.getRecentlyExecutedRollbacks()) {
- assertNotEquals(TEST_APP_B, r.targetPackage.packageName);
+ assertNotEquals(TEST_APP_B, r.targetPackage.getPackageName());
}
// TODO: Test the listed dependent apps for the recently executed
@@ -680,4 +652,15 @@ public class RollbackTest {
RollbackTestUtils.dropShellPermissionIdentity();
}
}
+
+ // Helper function to test the value of a PackageRollbackInfo
+ private void assertPackageRollbackInfoEquals(String packageName,
+ long versionRolledBackFrom, long versionRolledBackTo,
+ PackageRollbackInfo info) {
+ assertEquals(packageName, info.getPackageName());
+ assertEquals(packageName, info.getVersionRolledBackFrom().getPackageName());
+ assertEquals(versionRolledBackFrom, info.getVersionRolledBackFrom().getLongVersionCode());
+ assertEquals(packageName, info.getVersionRolledBackTo().getPackageName());
+ assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode());
+ }
}