Merge changes Id899f3c1,Ib262bc8c
* changes:
Test child sessions time out in enabling rollback (2/n)
Rewrite blockRollbackManager (1/n)
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 198bb14..01f29dc 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -49,6 +49,7 @@
import android.provider.DeviceConfig;
import android.util.ArraySet;
import android.util.IntArray;
+import android.util.LongArrayQueue;
import android.util.Slog;
import android.util.SparseBooleanArray;
@@ -126,6 +127,11 @@
private final RollbackPackageHealthObserver mPackageHealthObserver;
private final AppDataRollbackHelper mAppDataRollbackHelper;
+ // The # of milli-seconds to sleep for each received ACTION_PACKAGE_ENABLE_ROLLBACK.
+ // Used by #blockRollbackManager to test timeout in enabling rollbacks.
+ // Accessed on the handler thread only.
+ private final LongArrayQueue mSleepDuration = new LongArrayQueue();
+
// This field stores the difference in Millis between the uptime (millis since device
// has booted) and current time (device wall clock) - it's used to update rollback
// timestamps when the time is changed, by the user or by change of timezone.
@@ -182,6 +188,8 @@
File newPackageCodePath = new File(intent.getData().getPath());
+ queueSleepIfNeeded();
+
getHandler().post(() -> {
boolean success =
enableRollback(installFlags, newPackageCodePath, user, token);
@@ -414,6 +422,19 @@
Manifest.permission.TEST_MANAGE_ROLLBACKS,
"blockRollbackManager");
getHandler().post(() -> {
+ mSleepDuration.addLast(millis);
+ });
+ }
+
+ private void queueSleepIfNeeded() {
+ if (mSleepDuration.size() == 0) {
+ return;
+ }
+ long millis = mSleepDuration.removeFirst();
+ if (millis <= 0) {
+ return;
+ }
+ getHandler().post(() -> {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
@@ -1034,6 +1055,9 @@
makeRollbackAvailable(rollback);
}
}
+
+ // Clear the queue so it will never be leaked to next tests.
+ mSleepDuration.clear();
}
}
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 599ee56..abe6c61 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -1054,4 +1054,48 @@
InstallUtils.dropShellPermissionIdentity();
}
}
+
+ @Test
+ public void testEnableRollbackTimeoutFailsRollback_MultiPackage() throws Exception {
+ try {
+ InstallUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.TEST_MANAGE_ROLLBACKS,
+ Manifest.permission.MANAGE_ROLLBACKS,
+ Manifest.permission.WRITE_DEVICE_CONFIG);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+ PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
+ Long.toString(5000), false /* makeDefault*/);
+ RollbackManager rm = RollbackUtils.getRollbackManager();
+
+ Uninstall.packages(TestApp.A, TestApp.B);
+ Install.multi(TestApp.A1, TestApp.B1).commit();
+ waitForUnavailableRollback(TestApp.A);
+
+ // Block the 2nd session for 10s so it will not be able to enable the rollback in time.
+ rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(0));
+ rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(10));
+ Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit();
+
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+ assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
+
+ // Give plenty of time for RollbackManager to unblock and attempt
+ // to make the rollback available before asserting that the
+ // rollback was not made available.
+ Thread.sleep(TimeUnit.SECONDS.toMillis(2));
+
+ List<RollbackInfo> available = rm.getAvailableRollbacks();
+ assertThat(getUniqueRollbackInfoForPackage(available, TestApp.A)).isNull();
+ assertThat(getUniqueRollbackInfoForPackage(available, TestApp.B)).isNull();
+ } finally {
+ //setting the timeout back to default
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+ PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
+ null, false /* makeDefault*/);
+ InstallUtils.dropShellPermissionIdentity();
+ }
+ }
}