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();
+        }
+    }
 }