fs_mgr: handle more bootconfig parameters

As parameters are moved from kernel cmdline to bootconfig,
fs_mgr needs to be updated to handle the new location.
/proc/bootconfig should be checked first, if not present, then check
/proc/cmdline.

Test: atest CtsFsMgrTestCases
Test: launch_cvd
Test: launch_cvd with 4.19 kernel artifacts that do not support
bootconfig
Test: Both of the above configurations with --num_instances 0 or 4
Test: Both configurations with androidboot.boot_devices or
androidboot.boot_device set
Bug: 173815685

Change-Id: I23fb07a17c25c9459833cb931ced79d5ccc3e42a
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 1efe793..6952cdf 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -2203,7 +2203,8 @@
     // Devices upgrading to dynamic partitions are allowed to specify a super
     // partition name. This includes cuttlefish, which is a non-A/B device.
     std::string super_partition;
-    if (fs_mgr_get_boot_config_from_kernel_cmdline("super_partition", &super_partition)) {
+    if (fs_mgr_get_boot_config_from_bootconfig_source("super_partition", &super_partition) ||
+        fs_mgr_get_boot_config_from_kernel_cmdline("super_partition", &super_partition)) {
         if (fs_mgr_get_slot_suffix().empty()) {
             return super_partition;
         }
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 785a8e0..0c0862e 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -299,7 +299,8 @@
 std::string InitAndroidDtDir() {
     std::string android_dt_dir;
     // The platform may specify a custom Android DT path in kernel cmdline
-    if (!fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) {
+    if (!fs_mgr_get_boot_config_from_bootconfig_source("android_dt_dir", &android_dt_dir) &&
+        !fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) {
         // Fall back to the standard procfs-based path
         android_dt_dir = kDefaultAndroidDtDir;
     }
@@ -842,9 +843,22 @@
 }
 
 std::set<std::string> GetBootDevices() {
-    // First check the kernel commandline, then try the device tree otherwise
+    // First check bootconfig, then kernel commandline, then the device tree
     std::string dt_file_name = get_android_dt_dir() + "/boot_devices";
     std::string value;
+    if (fs_mgr_get_boot_config_from_bootconfig_source("boot_devices", &value) ||
+        fs_mgr_get_boot_config_from_bootconfig_source("boot_device", &value)) {
+        std::set<std::string> boot_devices;
+        // remove quotes and split by spaces
+        auto boot_device_strings = base::Split(base::StringReplace(value, "\"", "", true), " ");
+        for (std::string_view device : boot_device_strings) {
+            // trim the trailing comma, keep the rest.
+            base::ConsumeSuffix(&device, ",");
+            boot_devices.emplace(device);
+        }
+        return boot_devices;
+    }
+
     if (fs_mgr_get_boot_config_from_kernel_cmdline("boot_devices", &value) ||
         ReadDtFile(dt_file_name, &value)) {
         auto boot_devices = Split(value, ",");
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 62a8d3b..bcd5180 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -121,6 +121,7 @@
 
 const std::string bootconfig =
         "androidboot.bootdevice  = \" \"1d84000.ufshc\"\n"
+        "androidboot.boot_devices = \"dev1\", \"dev2,withcomma\", \"dev3\"\n"
         "androidboot.baseband = \"sdy\"\n"
         "androidboot.keymaster = \"1\"\n"
         "androidboot.serialno = \"BLAHBLAHBLAH\"\n"
@@ -152,6 +153,7 @@
 
 const std::vector<std::pair<std::string, std::string>> bootconfig_result_space = {
         {"androidboot.bootdevice", "1d84000.ufshc"},
+        {"androidboot.boot_devices", "dev1, dev2,withcomma, dev3"},
         {"androidboot.baseband", "sdy"},
         {"androidboot.keymaster", "1"},
         {"androidboot.serialno", "BLAHBLAHBLAH"},