Dump the root digest of hashtree for dm-verity partitions

It's requested by the partner engineering team to uniquely
identify a partition.

Bug: 197973981
Test: boot the device and check props
Change-Id: I0f7aa34dd0087f0698fe90b9df6c0eae06fc4f5d
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 5f15aad..002b302 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -2231,16 +2231,16 @@
     return false;
 }
 
-std::string fs_mgr_get_hashtree_algorithm(const android::fs_mgr::FstabEntry& entry) {
+std::optional<HashtreeInfo> fs_mgr_get_hashtree_info(const android::fs_mgr::FstabEntry& entry) {
     if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
-        return "";
+        return {};
     }
     DeviceMapper& dm = DeviceMapper::Instance();
     std::string device = GetVerityDeviceName(entry);
 
     std::vector<DeviceMapper::TargetInfo> table;
     if (dm.GetState(device) == DmDeviceState::INVALID || !dm.GetTableInfo(device, &table)) {
-        return "";
+        return {};
     }
     for (const auto& target : table) {
         if (strcmp(target.spec.target_type, "verity") != 0) {
@@ -2256,14 +2256,15 @@
         std::vector<std::string> tokens = android::base::Split(target.data, " \t\r\n");
         if (tokens[0] != "0" && tokens[0] != "1") {
             LOG(WARNING) << "Unrecognized device mapper version in " << target.data;
-            return "";
+            return {};
         }
 
-        // Hashtree algorithm is the 8th token in the output
-        return android::base::Trim(tokens[7]);
+        // Hashtree algorithm & root digest are the 8th & 9th token in the output.
+        return HashtreeInfo{.algorithm = android::base::Trim(tokens[7]),
+                            .root_digest = android::base::Trim(tokens[8])};
     }
 
-    return "";
+    return {};
 }
 
 bool fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry& entry) {
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 4d3ecc9..21c9989 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -22,6 +22,7 @@
 #include <linux/dm-ioctl.h>
 
 #include <functional>
+#include <optional>
 #include <string>
 
 #include <fstab/fstab.h>
@@ -68,6 +69,13 @@
     bool userdata_mounted;
 };
 
+struct HashtreeInfo {
+    // The hash algorithm used to build the merkle tree.
+    std::string algorithm;
+    // The root digest of the merkle tree.
+    std::string root_digest;
+};
+
 // fs_mgr_mount_all() updates fstab entries that reference device-mapper.
 // Returns a |MountAllResult|. The first element is one of the FS_MNG_MNTALL_* return codes
 // defined above, and the second element tells whether this call to fs_mgr_mount_all was responsible
@@ -88,9 +96,9 @@
 bool fs_mgr_load_verity_state(int* mode);
 // Returns true if verity is enabled on this particular FstabEntry.
 bool fs_mgr_is_verity_enabled(const android::fs_mgr::FstabEntry& entry);
-// Returns the hash algorithm used to build the hashtree of this particular FstabEntry. Returns an
-// empty string if the input isn't a dm-verity entry, or if there is an error.
-std::string fs_mgr_get_hashtree_algorithm(const android::fs_mgr::FstabEntry& entry);
+// Returns the verity hashtree information of this particular FstabEntry. Returns std::nullopt
+// if the input isn't a dm-verity entry, or if there is an error.
+std::optional<HashtreeInfo> fs_mgr_get_hashtree_info(const android::fs_mgr::FstabEntry& entry);
 
 bool fs_mgr_swapon_all(const android::fs_mgr::Fstab& fstab);
 bool fs_mgr_update_logical_partition(android::fs_mgr::FstabEntry* entry);
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 7633d9c..994eed9 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -894,9 +894,11 @@
         std::string partition = entry.mount_point == "/" ? "system" : Basename(entry.mount_point);
         SetProperty("partition." + partition + ".verified", std::to_string(mode));
 
-        std::string hash_alg = fs_mgr_get_hashtree_algorithm(entry);
-        if (!hash_alg.empty()) {
-            SetProperty("partition." + partition + ".verified.hash_alg", hash_alg);
+        auto hashtree_info = fs_mgr_get_hashtree_info(entry);
+        if (hashtree_info) {
+            SetProperty("partition." + partition + ".verified.hash_alg", hashtree_info->algorithm);
+            SetProperty("partition." + partition + ".verified.root_digest",
+                        hashtree_info->root_digest);
         }
     }