Avoid to format raw disk if metadata encryption is enabled

The current flow is

1. factory reset formatted raw disk.
2. next boot tries to convert it to metadata encryption
 2.a mount sda27
 2.b umount sda27
 2.c encrypt_inplace()
 2.d fsck on dm-x
 2.e mount dm-x

The #2 flow is unnecessary, if we know the disk will be encrypted. And, that
gives a change of the failure when unmounting the raw disk by starting some
file operations on /data. That can cause the entire encryption failure.

Bug: 208161227
Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
Change-Id: Iaedfeb74bb6abb667efee6dcadf8d66272466ee0
diff --git a/recovery_utils/roots.cpp b/recovery_utils/roots.cpp
index 0b82c1c..d761e75 100644
--- a/recovery_utils/roots.cpp
+++ b/recovery_utils/roots.cpp
@@ -34,6 +34,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <ext4_utils/ext4_utils.h>
+#include <ext4_utils/wipe.h>
 #include <fs_mgr.h>
 #include <fs_mgr/roots.h>
 
@@ -176,6 +177,25 @@
     }
   }
 
+  // If the raw disk will be used as a metadata encrypted device mapper target,
+  // next boot will do encrypt_in_place the raw disk which gives a subtle duration
+  // to get any failure in the process. In order to avoid it, let's simply wipe
+  // the raw disk if we don't reserve any space, which behaves exactly same as booting
+  // after "fastboot -w".
+  if (!v->metadata_encryption.empty() && length == 0) {
+    android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDWR));
+    if (fd == -1) {
+      PLOG(ERROR) << "format_volume: failed to open " << v->blk_device;
+      return -1;
+    }
+    int64_t device_size = get_file_size(fd.get(), 0);
+    if (device_size > 0 && !wipe_block_device(fd.get(), device_size)) {
+      LOG(INFO) << "format_volume: wipe metadata encrypted " << v->blk_device << " with size "
+                << device_size;
+      return 0;
+    }
+  }
+
   if (v->fs_type == "ext4") {
     static constexpr int kBlockSize = 4096;
     std::vector<std::string> mke2fs_args = {