From 0a79b323320d09dd0d4478283e5d999da728b168 Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Wed, 23 Jan 2019 13:51:07 +0000 Subject: Include all relevant packages in RollbackInfo. Instead of a single target package. Needed for rollback of multiPackage installs. Additionally, expose this information by a public method rather than a public field. Bug: 112431924 Test: atest RollbackTest Change-Id: I6e3ce87385abd37c48047db27bc443d3719ee023 --- api/system-current.txt | 2 +- .../android/content/rollback/RollbackInfo.java | 24 ++-- .../rollback/RollbackManagerServiceImpl.java | 56 +++++--- .../com/android/server/rollback/RollbackStore.java | 75 +++++----- .../com/android/tests/rollback/RollbackTest.java | 159 +++++++++++---------- 5 files changed, 176 insertions(+), 140 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 213aedc4b44d..1c63aa35ea9f 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1695,10 +1695,10 @@ package android.content.rollback { public final class RollbackInfo implements android.os.Parcelable { method public int describeContents(); + method public java.util.List getPackages(); method public int getRollbackId(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; - field public final android.content.rollback.PackageRollbackInfo targetPackage; } public final class RollbackManager { 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 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 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 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 CREATOR = diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 8b4c410000bb..815fca31095b 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -219,7 +219,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { 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 new RollbackInfo(data.rollbackId, data.packages); } } return null; @@ -279,18 +279,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 +328,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 +338,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); @@ -406,7 +398,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 +529,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 +930,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/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 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 infos) throws JSONException { + JSONArray json = new JSONArray(); + for (PackageRollbackInfo info : infos) { + json.put(toJson(info)); + } + return json; + } + + private List packageRollbackInfosFromJson(JSONArray json) + throws JSONException { + List 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/RollbackTest.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 13ac4f09dd86..054d5f901773 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -32,7 +32,6 @@ 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; @@ -43,6 +42,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; @@ -99,12 +99,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.getRecentlyExecutedRollbacks(), TEST_APP_A); + if (rollback != null) { + Log.i(TAG, "Sleeping 1 second to wait for uninstall to take effect."); + Thread.sleep(1000); } } @@ -117,9 +116,8 @@ public class RollbackTest { assertFalse(rm.getPackagesWithAvailableRollbacks().contains(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()); - } + assertNull(getUniqueRollbackInfoForPackage( + rm.getRecentlyExecutedRollbacks(), TEST_APP_A)); // Install v1 of the app (without rollbacks enabled). RollbackTestUtils.install("RollbackTestAppAv1.apk", false); @@ -136,8 +134,7 @@ public class RollbackTest { 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); + 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 +153,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.getRecentlyExecutedRollbacks(), TEST_APP_A); + assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); broadcastReceiver.unregister(); context.unregisterReceiver(enableRollbackReceiver); @@ -204,26 +195,22 @@ public class RollbackTest { assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A)); RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A); - assertNotNull(rollbackA); - assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage); + 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); + 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); + 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); + assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); // Rollback of B should not rollback A RollbackTestUtils.rollback(rollbackB); @@ -266,26 +253,23 @@ public class RollbackTest { assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A)); RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A); - assertNotNull(rollbackA); - assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage); + 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); + assertRollbackInfoForAandB(rollbackB); // Reload the persisted data. rm.reloadPersistedData(); // The apps should still be available for rollback. + assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A)); rollbackA = rm.getAvailableRollback(TEST_APP_A); - assertNotNull(rollbackA); - assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA.targetPackage); + 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); + assertRollbackInfoForAandB(rollbackB); // Rollback of B should rollback A as well RollbackTestUtils.rollback(rollbackB); @@ -327,29 +311,19 @@ public class RollbackTest { 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.getRecentlyExecutedRollbacks(), 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.getRecentlyExecutedRollbacks(), TEST_APP_A); assertNotNull(rollback); - assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.targetPackage); + assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); } finally { RollbackTestUtils.dropShellPermissionIdentity(); } @@ -380,8 +354,7 @@ public class RollbackTest { 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); + assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); // Expire the rollback. rm.expireRollbackForPackage(TEST_APP_A); @@ -516,18 +489,16 @@ 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()); + assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B); - assertNotNull(rollbackB); - assertEquals(TEST_APP_B, rollbackB.targetPackage.getPackageName()); + assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); // Executing rollback should roll back the correct package. RollbackTestUtils.rollback(rollbackA); @@ -631,10 +602,7 @@ public class RollbackTest { // 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. + assertRollbackInfoForAandB(rollback); // Rollback the app. It should cause both test apps to be rolled // back. @@ -642,14 +610,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.getRecentlyExecutedRollbacks(), TEST_APP_A); + + RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( + rm.getRecentlyExecutedRollbacks(), TEST_APP_B); + assertRollbackInfoForAandB(rollbackB); - // TODO: Test the listed dependent apps for the recently executed - // rollback are correct once we support that in the RollbackInfo - // API. + assertEquals(rollbackA.getRollbackId(), rollbackB.getRollbackId()); } finally { RollbackTestUtils.dropShellPermissionIdentity(); } @@ -699,11 +669,11 @@ public class RollbackTest { Thread.sleep(1000); RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A); assertNotNull(rollbackA); - assertEquals(TEST_APP_A, rollbackA.targetPackage.getPackageName()); + assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B); assertNotNull(rollbackB); - assertEquals(TEST_APP_B, rollbackB.targetPackage.getPackageName()); + 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 +694,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 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; + } } -- cgit v1.2.3-59-g8ed1b From 150ad9865e8a92f36d27e4bf9bbd1a6404e2a909 Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Wed, 23 Jan 2019 15:16:10 +0000 Subject: Add RollbackManager.getAvailableRollbacks API. To replace getAvailableRollback and getPackagesWithAvailableRollbacks, which will be removed in a subsequent CL. Bug: 112431924 Test: atest RollbackTest Change-Id: I67adeb41df974aa5b375f16becdad5910ccc9c76 --- api/system-current.txt | 1 + .../android/content/rollback/IRollbackManager.aidl | 6 +--- .../android/content/rollback/RollbackManager.java | 41 +++++++++++++++++----- .../rollback/RollbackManagerServiceImpl.java | 41 +++------------------- 4 files changed, 39 insertions(+), 50 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 1c63aa35ea9f..8b67deb4877d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1705,6 +1705,7 @@ package android.content.rollback { 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 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) public java.util.List getAvailableRollbacks(); method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List getPackagesWithAvailableRollbacks(); method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List getRecentlyExecutedRollbacks(); method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void reloadPersistedData(); 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/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java index c1c0bc1d3e07..564839b46896 100644 --- a/core/java/android/content/rollback/RollbackManager.java +++ b/core/java/android/content/rollback/RollbackManager.java @@ -25,6 +25,7 @@ import android.content.Context; import android.content.IntentSender; import android.os.RemoteException; +import java.util.ArrayList; import java.util.List; /** @@ -49,6 +50,21 @@ public final class RollbackManager { mBinder = binder; } + /** + * Returns a list of all currently available rollbacks. + * + * @throws SecurityException if the caller does not have the + * MANAGE_ROLLBACKS permission. + */ + @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) + public List getAvailableRollbacks() { + try { + return mBinder.getAvailableRollbacks().getList(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Returns the rollback currently available to be executed for the given * package. @@ -57,7 +73,7 @@ public final class RollbackManager { * including package version codes before and after rollback. The rollback * can be initiated using {@link #executeRollback(RollbackInfo,IntentSender)}. *

- * TODO: What if there is no package installed on device for packageName? + * TODO: remove this API in favor of getAvailableRollbacks. * * @param packageName name of the package to get the availble RollbackInfo for. * @return the rollback available for the package, or null if no rollback @@ -67,17 +83,22 @@ public final class RollbackManager { */ @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public @Nullable RollbackInfo getAvailableRollback(@NonNull String packageName) { - try { - return mBinder.getAvailableRollback(packageName); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + for (RollbackInfo rollback : getAvailableRollbacks()) { + for (PackageRollbackInfo info : rollback.getPackages()) { + if (packageName.equals(info.getPackageName())) { + return rollback; + } + } } + return null; } /** * 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. + *

+ * TODO: remove this API in favor of getAvailableRollbacks. * * @return the names of packages that are available for rollback. * @throws SecurityException if the caller does not have the @@ -85,11 +106,13 @@ public final class RollbackManager { */ @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public @NonNull List getPackagesWithAvailableRollbacks() { - try { - return mBinder.getPackagesWithAvailableRollbacks().getList(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + List packages = new ArrayList<>(); + for (RollbackInfo rollbacks : getAvailableRollbacks()) { + for (PackageRollbackInfo info : rollbacks.getPackages()) { + packages.add(info.getPackageName()); + } } + return packages; } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 815fca31095b..7d2f2ab95de3 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, data.packages); - } - } - return null; - } - - @Override - public StringParceledListSlice getPackagesWithAvailableRollbacks() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_ROLLBACKS, - "getPackagesWithAvailableRollbacks"); - - final Set packageNames = new HashSet<>(); synchronized (mLock) { ensureRollbackDataLoadedLocked(); + List 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 -- cgit v1.2.3-59-g8ed1b From 0e96192e45a3926f14e3ceeb88420ef481c651fc Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Fri, 25 Jan 2019 13:07:08 +0000 Subject: Use new RollbackManager API in RollbackPackageHealthObserver. Use RollbackManager.getAvailableRollbacks instead of RollbackManager.getAvailableRollback, which will be removed shortly. Bug: 112431924 Test: atest RollbackTest Change-Id: Ia6548e4d66da3484cb90ab6f20832356628f1881 --- .../server/rollback/RollbackPackageHealthObserver.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java index 1f2f1ccd7383..6aa44a70c268 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; -- cgit v1.2.3-59-g8ed1b From beb7e38f39f1a0d9a6f743b060904634ea105364 Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Wed, 23 Jan 2019 15:48:29 +0000 Subject: Use RollbackManager.getAvailableRollbacks in RollbackTest Instead of getAvailableRollback and getPackagesWithAvailableRollbacks, which are soon to be removed. Bug: 112431924 Test: atest RollbackTest Change-Id: Ia69342a41bebb91a9fa8044ef8d8b495aba7187f --- .../com/android/tests/rollback/RollbackTest.java | 80 ++++++++++------------ 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 054d5f901773..7b9b3423968d 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -31,10 +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.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.junit.Ignore; @@ -112,8 +110,7 @@ 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. assertNull(getUniqueRollbackInfoForPackage( @@ -132,8 +129,8 @@ 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); assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); // We should not have received any rollback requests yet. @@ -193,23 +190,24 @@ public class RollbackTest { // is made available. Thread.sleep(1000); - assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A)); - RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A); + 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); + 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); + 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); + rollbackB = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TEST_APP_B); assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); // Rollback of B should not rollback A @@ -251,24 +249,22 @@ public class RollbackTest { // is made available. Thread.sleep(1000); - assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A)); - RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A); + RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TEST_APP_A); assertRollbackInfoForAandB(rollbackA); - assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B)); - RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B); + RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TEST_APP_B); assertRollbackInfoForAandB(rollbackB); // Reload the persisted data. rm.reloadPersistedData(); // The apps should still be available for rollback. - assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A)); - rollbackA = rm.getAvailableRollback(TEST_APP_A); + rollbackA = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A); assertRollbackInfoForAandB(rollbackA); - assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B)); - rollbackB = rm.getAvailableRollback(TEST_APP_B); + rollbackB = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_B); assertRollbackInfoForAandB(rollbackB); // Rollback of B should rollback A as well @@ -303,8 +299,8 @@ 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); @@ -352,16 +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); + 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(); } @@ -432,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 { @@ -494,10 +491,12 @@ 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); + RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TEST_APP_A); assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); - RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B); + RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TEST_APP_B); assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); // Executing rollback should roll back the correct package. @@ -529,14 +528,7 @@ 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. @@ -600,8 +592,8 @@ 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); + RollbackInfo rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TEST_APP_A); assertRollbackInfoForAandB(rollback); // Rollback the app. It should cause both test apps to be rolled @@ -667,12 +659,12 @@ 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); + RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TEST_APP_A); assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); - RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B); - assertNotNull(rollbackB); + 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 -- cgit v1.2.3-59-g8ed1b From 65f9717b6ff48a90ae062293d7c73928165792e4 Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Thu, 24 Jan 2019 09:22:13 +0000 Subject: Remove unused RollbackManager APIs. RollbackManager.getAvailableRollback and getPackagesWithAvailableRollback are no longer needed given the getAvailableRollbacks API. Remove them. Bug: 112431924 Test: atest RollbackTest Change-Id: I88a50a0efd97dd5b45c68e0a3e3253f11d0284f6 --- api/system-current.txt | 2 - .../android/content/rollback/RollbackManager.java | 55 +--------------------- 2 files changed, 1 insertion(+), 56 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 8b67deb4877d..82802415155c 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1704,9 +1704,7 @@ package android.content.rollback { 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 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) public java.util.List getAvailableRollbacks(); - method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List getPackagesWithAvailableRollbacks(); method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List getRecentlyExecutedRollbacks(); method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void reloadPersistedData(); } diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java index 564839b46896..b552ad59aee5 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; @@ -25,7 +24,6 @@ import android.content.Context; import android.content.IntentSender; import android.os.RemoteException; -import java.util.ArrayList; import java.util.List; /** @@ -65,57 +63,6 @@ public final class RollbackManager { } } - /** - * Returns the rollback currently available to be executed for the given - * package. - *

- * 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)}. - *

- * TODO: remove this API in favor of getAvailableRollbacks. - * - * @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) { - for (RollbackInfo rollback : getAvailableRollbacks()) { - for (PackageRollbackInfo info : rollback.getPackages()) { - if (packageName.equals(info.getPackageName())) { - return rollback; - } - } - } - return null; - } - - /** - * 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. - *

- * TODO: remove this API in favor of getAvailableRollbacks. - * - * @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 getPackagesWithAvailableRollbacks() { - List packages = new ArrayList<>(); - for (RollbackInfo rollbacks : getAvailableRollbacks()) { - for (PackageRollbackInfo info : rollbacks.getPackages()) { - packages.add(info.getPackageName()); - } - } - return packages; - } - - /** * Gets the list of all recently executed rollbacks. * This is for the purposes of preventing re-install of a bad version of a @@ -150,7 +97,7 @@ public final class RollbackManager { * 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)}. + * object was retrieved from {@link #getAvailableRollbacks()}. *

* TODO: Specify the returns status codes. * TODO: What happens in case reboot is required for the rollback to take -- cgit v1.2.3-59-g8ed1b From dca7beb7401ee49e4863a103bfd8c1e50de11b14 Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Thu, 24 Jan 2019 09:56:03 +0000 Subject: Rename PACKAGE_ROLLBACK_EXECUTED to ROLLBACK_COMMITTED. Because there's no need to distinguish between package and other kinds of rollbacks, and for rollback of staged installs, committed is a more appropriate name than executed. Bug: 112431924 Test: atest RollbackTest Change-Id: I2a409de29ba82a7a3df2fd0b17f939795caa61d5 --- api/system-current.txt | 2 +- core/java/android/content/Intent.java | 7 +++---- core/res/AndroidManifest.xml | 2 +- .../com/android/server/rollback/RollbackManagerServiceImpl.java | 2 +- .../src/com/android/tests/rollback/RollbackBroadcastReceiver.java | 4 ++-- .../RollbackTest/src/com/android/tests/rollback/RollbackTest.java | 4 ++-- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 82802415155c..51dde71d343f 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"; diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index edd765b05415..aa559ba11a05 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. * *

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/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 @@ - + diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 7d2f2ab95de3..6487bd7af7ee 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -353,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. 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 7b9b3423968d..452ac8bda786 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -439,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."); -- cgit v1.2.3-59-g8ed1b From 4b092ef6f75a8c8137bf37ab1c0905faf58da31a Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Thu, 24 Jan 2019 13:08:38 +0000 Subject: Use "commit" instead of "execute" for rollbacks. Which makes more sense for rollback of staged installs, where the caller will have to reboot the device before the rollback takes effect. Internal references to "execute" in IRollbackManager.aidl and the rollback manager service implementation will be renamed in a follow up CL. Bug: 112431924 Test: atest RollbackTest Change-Id: Ic2bb479873b309fc145e4eda3b347849ac219ac9 --- api/system-current.txt | 4 +-- .../android/content/rollback/RollbackManager.java | 31 +++++++++++----------- .../rollback/RollbackPackageHealthObserver.java | 2 +- .../com/android/tests/rollback/RollbackTest.java | 28 +++++++++---------- .../android/tests/rollback/RollbackTestUtils.java | 4 +-- 5 files changed, 34 insertions(+), 35 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 51dde71d343f..24191b76f587 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1702,10 +1702,10 @@ package android.content.rollback { } 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) public java.util.List getAvailableRollbacks(); - method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List getRecentlyExecutedRollbacks(); + method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) @NonNull public java.util.List getRecentlyCommittedRollbacks(); method @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void reloadPersistedData(); } diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java index b552ad59aee5..2566ac562e11 100644 --- a/core/java/android/content/rollback/RollbackManager.java +++ b/core/java/android/content/rollback/RollbackManager.java @@ -64,11 +64,11 @@ public final class RollbackManager { } /** - * 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. *

- * Returns an empty list if there are no recently executed rollbacks. + * Returns an empty list if there are no recently committed rollbacks. *

* To avoid having to keep around complete rollback history forever on a * device, the returned list of rollbacks is only guaranteed to include @@ -77,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 getRecentlyExecutedRollbacks() { + public @NonNull List getRecentlyCommittedRollbacks() { try { return mBinder.getRecentlyExecutedRollbacks().getList(); } catch (RemoteException e) { @@ -91,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 #getAvailableRollbacks()}. + * 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()}. *

* 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/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java index 6aa44a70c268..3954a1178e09 100644 --- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java @@ -88,7 +88,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve } }); }); - manager.executeRollback(rollback, rollbackReceiver.getIntentSender()); + manager.commitRollback(rollback, rollbackReceiver.getIntentSender()); } @Override diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 452ac8bda786..7ab716fac6df 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -84,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(); @@ -98,7 +98,7 @@ public class RollbackTest { // so that's not the case! for (int i = 0; i < 5; ++i) { RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyExecutedRollbacks(), TEST_APP_A); + rm.getRecentlyCommittedRollbacks(), TEST_APP_A); if (rollback != null) { Log.i(TAG, "Sleeping 1 second to wait for uninstall to take effect."); Thread.sleep(1000); @@ -112,9 +112,9 @@ public class RollbackTest { Thread.sleep(1000); assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); - // There should be no recently executed rollbacks for this package. + // There should be no recently committed rollbacks for this package. assertNull(getUniqueRollbackInfoForPackage( - rm.getRecentlyExecutedRollbacks(), TEST_APP_A)); + rm.getRecentlyCommittedRollbacks(), TEST_APP_A)); // Install v1 of the app (without rollbacks enabled). RollbackTestUtils.install("RollbackTestAppAv1.apk", false); @@ -151,7 +151,7 @@ public class RollbackTest { // Verify the recent rollback has been recorded. rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyExecutedRollbacks(), TEST_APP_A); + rm.getRecentlyCommittedRollbacks(), TEST_APP_A); assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); broadcastReceiver.unregister(); @@ -277,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, @@ -308,7 +308,7 @@ public class RollbackTest { // Verify the recent rollback has been recorded. rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyExecutedRollbacks(), TEST_APP_A); + rm.getRecentlyCommittedRollbacks(), TEST_APP_A); assertNotNull(rollback); assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); @@ -317,7 +317,7 @@ public class RollbackTest { // Verify the recent rollback is still recorded. rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyExecutedRollbacks(), TEST_APP_A); + rm.getRecentlyCommittedRollbacks(), TEST_APP_A); assertNotNull(rollback); assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); } finally { @@ -535,7 +535,7 @@ public class RollbackTest { } try { - rm.getRecentlyExecutedRollbacks(); + rm.getRecentlyCommittedRollbacks(); fail("expected SecurityException"); } catch (SecurityException e) { // Expected. @@ -544,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. @@ -605,10 +605,10 @@ public class RollbackTest { // We should see recent rollbacks listed for both A and B. Thread.sleep(1000); RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getRecentlyExecutedRollbacks(), TEST_APP_A); + rm.getRecentlyCommittedRollbacks(), TEST_APP_A); RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getRecentlyExecutedRollbacks(), TEST_APP_B); + rm.getRecentlyCommittedRollbacks(), TEST_APP_B); assertRollbackInfoForAandB(rollbackB); assertEquals(rollbackA.getRollbackId(), rollbackB.getRollbackId()); 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()); } -- cgit v1.2.3-59-g8ed1b