Add IVold::destroyDsuMetadataKey()

destroyDsuMetadataKey() / destroy_dsu_metadata_key() calls
android::gsi::GetDsuMetadataKeyDir() to query the DSU metadata
encryption key dir and destroy the key.
This releases the resource and allows consecutive DSU installations to
use the same key *directory*, but not the same key *blob*.

Bug: 168571434
Test: 1. Install a DSU system.
  2. Boot the DSU system and reboot back to the host system.
  3. Wipe the DSU installation.
  4. DSU metadata key dir /metadata/vold/metadata_encryption/dsu/dsu is
     destroyed.
Change-Id: Ib851177315a5a266807f46ccfd446de1848232cf
diff --git a/Android.bp b/Android.bp
index 4852fe4..1c0ed17 100644
--- a/Android.bp
+++ b/Android.bp
@@ -54,6 +54,7 @@
         "libdiskconfig",
         "libext4_utils",
         "libf2fs_sparseblock",
+        "libgsi",
         "libhardware",
         "libhardware_legacy",
         "libincfs",
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index c61132c..52add4a 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -35,6 +35,7 @@
 #include <cutils/fs.h>
 #include <fs_mgr.h>
 #include <libdm/dm.h>
+#include <libgsi/libgsi.h>
 
 #include "Checkpoint.h"
 #include "CryptoType.h"
@@ -366,5 +367,44 @@
     return create_crypto_blk_dev(label, blk_device, key, options, out_crypto_blkdev, &nr_sec);
 }
 
+bool destroy_dsu_metadata_key(const std::string& dsu_slot) {
+    LOG(DEBUG) << "destroy_dsu_metadata_key: " << dsu_slot;
+
+    const auto dsu_metadata_key_dir = android::gsi::GetDsuMetadataKeyDir(dsu_slot);
+    if (!pathExists(dsu_metadata_key_dir)) {
+        LOG(DEBUG) << "DSU metadata_key_dir doesn't exist, nothing to remove: "
+                   << dsu_metadata_key_dir;
+        return true;
+    }
+
+    // Ensure that the DSU key directory is different from the host OS'.
+    // Under normal circumstances, this should never happen, but handle it just in case.
+    if (auto data_rec = GetEntryForMountPoint(&fstab_default, "/data")) {
+        if (dsu_metadata_key_dir == data_rec->metadata_key_dir) {
+            LOG(ERROR) << "DSU metadata_key_dir is same as host OS: " << dsu_metadata_key_dir;
+            return false;
+        }
+    }
+
+    bool ok = true;
+    for (auto suffix : {"/key", "/tmp"}) {
+        const auto key_path = dsu_metadata_key_dir + suffix;
+        if (pathExists(key_path)) {
+            LOG(DEBUG) << "Destroy key: " << key_path;
+            if (!android::vold::destroyKey(key_path)) {
+                LOG(ERROR) << "Failed to destroyKey(): " << key_path;
+                ok = false;
+            }
+        }
+    }
+    if (!ok) {
+        return false;
+    }
+
+    LOG(DEBUG) << "Remove DSU metadata_key_dir: " << dsu_metadata_key_dir;
+    // DeleteDirContentsAndDir() already logged any error, so don't log repeatedly.
+    return android::vold::DeleteDirContentsAndDir(dsu_metadata_key_dir) == android::OK;
+}
+
 }  // namespace vold
 }  // namespace android
diff --git a/MetadataCrypt.h b/MetadataCrypt.h
index dc68e7c..7341a08 100644
--- a/MetadataCrypt.h
+++ b/MetadataCrypt.h
@@ -34,6 +34,8 @@
                                  const android::vold::KeyBuffer& key,
                                  std::string* out_crypto_blkdev);
 
+bool destroy_dsu_metadata_key(const std::string& dsu_slot);
+
 }  // namespace vold
 }  // namespace android
 #endif
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index d310acd..3fb4e65 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -950,5 +950,12 @@
     return translate(incfs::bindMount(sourceDir, targetDir));
 }
 
+binder::Status VoldNativeService::destroyDsuMetadataKey(const std::string& dsuSlot) {
+    ENFORCE_SYSTEM_OR_ROOT;
+    ACQUIRE_LOCK;
+
+    return translateBool(destroy_dsu_metadata_key(dsuSlot));
+}
+
 }  // namespace vold
 }  // namespace android
diff --git a/VoldNativeService.h b/VoldNativeService.h
index f10bf5f..9914879 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -159,6 +159,8 @@
             const ::android::os::incremental::IncrementalFileSystemControlParcel& control,
             bool enableReadLogs) override;
     binder::Status bindMount(const std::string& sourceDir, const std::string& targetDir) override;
+
+    binder::Status destroyDsuMetadataKey(const std::string& dsuSlot) override;
 };
 
 }  // namespace vold
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 61e1e54..1d6225f 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -139,6 +139,8 @@
     void setIncFsMountOptions(in IncrementalFileSystemControlParcel control, boolean enableReadLogs);
     void bindMount(@utf8InCpp String sourceDir, @utf8InCpp String targetDir);
 
+    void destroyDsuMetadataKey(@utf8InCpp String dsuSlot);
+
     const int ENCRYPTION_FLAG_NO_UI = 4;
 
     const int ENCRYPTION_STATE_NONE = 1;