diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 9324870904d98..6cdfcff614151 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -58,6 +58,7 @@ import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.PackageWatchdog; +import com.android.server.SystemConfig; import com.android.server.Watchdog; import com.android.server.pm.Installer; @@ -1008,10 +1009,18 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { installerPackageName) == PackageManager.PERMISSION_GRANTED; // For now only allow rollbacks for modules or for testing. - return (isModule(packageName) && manageRollbacksGranted) + return (isRollbackWhitelisted(packageName) && manageRollbacksGranted) || testManageRollbacksGranted; } + /** + * Returns true is this package is eligible for enabling rollback. + */ + private boolean isRollbackWhitelisted(String packageName) { + // TODO: Remove #isModule when the white list is ready. + return SystemConfig.getInstance().getRollbackWhitelistedPackages().contains(packageName) + || isModule(packageName); + } /** * Returns true if the package name is the name of a module. */ diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index abe6c6152da5a..daa85bd066690 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -1098,4 +1098,28 @@ public class RollbackTest { InstallUtils.dropShellPermissionIdentity(); } } + + /** + * Test we can't enable rollback for non-whitelisted app without + * TEST_MANAGE_ROLLBACKS permission + */ + @Test + public void testNonRollbackWhitelistedApp() throws Exception { + try { + InstallUtils.adoptShellPermissionIdentity( + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.DELETE_PACKAGES, + Manifest.permission.MANAGE_ROLLBACKS); + + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNull(); + + Install.single(TestApp.A2).setEnableRollback().commit(); + Thread.sleep(TimeUnit.SECONDS.toMillis(2)); + assertThat(RollbackUtils.getAvailableRollback(TestApp.A)).isNull(); + } finally { + InstallUtils.dropShellPermissionIdentity(); + } + } } diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java index 7b289d8a78581..879ac64c6a550 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java @@ -40,6 +40,7 @@ import com.android.cts.install.lib.TestApp; import com.android.cts.install.lib.Uninstall; import com.android.cts.rollback.lib.Rollback; import com.android.cts.rollback.lib.RollbackUtils; +import com.android.internal.R; import libcore.io.IoUtils; @@ -341,6 +342,37 @@ public class StagedRollbackTest { getNetworkStackPackageName())).isNull(); } + private static String getModuleMetadataPackageName() { + return InstrumentationRegistry.getInstrumentation().getContext() + .getResources().getString(R.string.config_defaultModuleMetadataProvider); + } + + @Test + public void testRollbackWhitelistedApp_Phase1() throws Exception { + // Remove available rollbacks + String pkgName = getModuleMetadataPackageName(); + RollbackUtils.getRollbackManager().expireRollbackForPackage(pkgName); + assertThat(RollbackUtils.getAvailableRollback(pkgName)).isNull(); + + // Overwrite existing permissions. We don't want TEST_MANAGE_ROLLBACKS which allows us + // to enable rollback for any app + InstallUtils.adoptShellPermissionIdentity( + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.MANAGE_ROLLBACKS); + + // Re-install a whitelisted app with rollbacks enabled + String filePath = InstrumentationRegistry.getInstrumentation().getContext() + .getPackageManager().getPackageInfo(pkgName, 0).applicationInfo.sourceDir; + TestApp app = new TestApp("ModuleMetadata", pkgName, -1, false, new File(filePath)); + Install.single(app).setStaged().setEnableRollback() + .addInstallFlags(PackageManager.INSTALL_REPLACE_EXISTING).commit(); + } + + @Test + public void testRollbackWhitelistedApp_Phase2() throws Exception { + assertThat(RollbackUtils.getAvailableRollback(getModuleMetadataPackageName())).isNotNull(); + } + private static void runShellCommand(String cmd) { ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation() .executeShellCommand(cmd); diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java index e4a8febb8bce5..07d829d2d0bbe 100644 --- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java +++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java @@ -175,6 +175,16 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { runPhase("testPreviouslyAbandonedRollbacks_Phase3"); } + /** + * Tests we can enable rollback for a whitelisted app. + */ + @Test + public void testRollbackWhitelistedApp() throws Exception { + runPhase("testRollbackWhitelistedApp_Phase1"); + getDevice().reboot(); + runPhase("testRollbackWhitelistedApp_Phase2"); + } + private void crashProcess(String processName, int numberOfCrashes) throws Exception { String pid = ""; String lastPid = "invalid";