Await boot_completed before allowing GC

Add a global that tracks whether `sys.boot_completed` has reached 1,
together with an accessor.

At start of day, kick off a thread that monitors for the property
getting set.  When it does get set, kick off a GC and exit the
monitoring thread.

In the garbage collection code, avoid performing GC until boot
has completed, so as to avoid doing any deleteKey() operations
that would prevent a failed OTA from being successfully rolled back.

Adapted from https://android-review.git.corp.google.com/c/platform/system/security/+/3445820/4

Bug: 388723650
Flag: EXEMPT bugfix

Test: atest keystore2_client_tests
Test: atest CtsKeystoreTestCases
Test: On a device that supports rollback-resistant Keystore keys,
      manually tested that this CL fixes the bug:
      1. Flashed udc-d1-release
      2. Completed setup wizard, but didn't set an LSKF
      3. Checked out 24Q3-release
      4. Patched system_server to crash the main thread with an
         exception after the LockSettingsService migration code has run
      5. Applied this CL (when applicable)
      6. m dist
      7. system/update_engine/scripts/update_device.py <path-to-ota-package>
      8. adb reboot
      9. Collected logcat for boot on new build
      10. Waited for rollback, then collected logcat again

      Tested without and with this CL applied in (5).  Observed that
      without this CL, boot failed after rollback, and logcat contained
      errors about the synthetic password failing to be decrypted due to
      an invalid Keymint blob.  Observed that with this CL, the rollback
      succeeds and logcat shows that the user's CE storage was unlocked.

Change-Id: Ibc5c137e8e5b2ebff762191e19095aa9bd05f749
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index 66b123e..626a1c0 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -2440,8 +2440,10 @@
             .context("Trying to delete grants.")?;
         // The associated blobentry rows are not immediately deleted when the owning keyentry is
         // removed, because a KeyMint `deleteKey()` invocation is needed (specifically for the
-        // `KEY_BLOB`).  Mark the affected rows with `state=Orphaned` so a subsequent garbage
-        // collection can do this.
+        // `KEY_BLOB`).  That should not be done from within the database transaction.  Also, calls
+        // to `deleteKey()` need to be delayed until the boot has completed, to avoid making
+        // permanent changes during an OTA before the point of no return.  Mark the affected rows
+        // with `state=Orphaned` so a subsequent garbage collection can do the `deleteKey()`.
         tx.execute(
             "UPDATE persistent.blobentry SET state = ? WHERE keyentryid = ?",
             params![BlobState::Orphaned, key_id],