Defer CE key fixations to checkpoint commit

On the first boot after an upgrade, ensure that any Keystore key
deletions triggered by fscrypt_set_user_key_protection() are deferred
until the userdata filesystem checkpoint is committed, so that the
system doesn't end up in a bad state if the checkpoint is rolled back.

Test: see I77d30f9be57de7b7c4818680732331549ecb73c8
Bug: 232452368
Ignore-AOSP-First: depends on other changes in internal master
Change-Id: I59b758bc13b7a2ae270f1a6c409affe2eb61119c
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index 948231d..3825af9 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -16,6 +16,8 @@
 
 #define LOG_TAG "Checkpoint"
 #include "Checkpoint.h"
+#include "FsCrypt.h"
+#include "KeyStorage.h"
 #include "VoldUtil.h"
 #include "VolumeManager.h"
 
@@ -78,6 +80,18 @@
     return true;
 }
 
+// Do any work that was deferred until the userdata filesystem checkpoint was
+// committed.  This work involves the deletion of resources that aren't covered
+// by the userdata filesystem checkpoint, e.g. Keystore keys.
+void DoCheckpointCommittedWork() {
+    // Take the crypt lock to provide synchronization with the Binder calls that
+    // operate on key directories.
+    std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getCryptLock());
+
+    DeferredCommitKeystoreKeys();
+    fscrypt_deferred_fixate_ce_keys();
+}
+
 }  // namespace
 
 Status cp_supportsCheckpoint(bool& result) {
@@ -205,6 +219,7 @@
     if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
         return error(err_str.c_str());
 
+    std::thread(DoCheckpointCommittedWork).detach();
     return Status::ok();
 }