init: Unify kernel bootconfig parser with libfs_mgr

Right now there are two bootconfig parsers that gets linked into `init`.
One is from libinit itself and the other is from libfs_mgr.

The one in libinit removes all space characters between list elements,
so `key = "val1", "val2"` gets unquoted and squeezed into:
  `key=val1,val2`
The one in libfs_mgr doesn't remove spaces, it only unquotes:
  `key=val1, val2`

The libinit behavior is due to existing systems (such as sysprop)
expect the config value to be in the same format as kernel cmdline.
(aosp/1757971)
THe libfs_mgr behavior is due to the `androidboot.boot_device[s]`
format explicitly allows quoted comma appear in its list value, thus
relies on space, not comma, as the list value delimeter.

This commit merges the two parsers into libfs_mgr. Since all usages in
libfs_mgr besides `boot_device[s]` do not care about how list value are
delimited, and most usages in init expects the bootconfig value format
to be the same format as cmdline. We just special case the
`boot_device` scenario.

Also harden the test cases to cover all the different config value
format and expected result.

Note:
The format of kernel bootconfig is described here
https://docs.kernel.org/admin-guide/bootconfig.html

Bug: 293695109
Test: CtsFsMgrTestCases
Change-Id: I42b9bf626e8de38a60e8e09fac0693126b7efd91
diff --git a/init/devices.cpp b/init/devices.cpp
index 7c23492..6b8474e 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -32,6 +32,7 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <fs_mgr.h>
 #include <libdm/dm.h>
 #include <private/android_filesystem_config.h>
 #include <selinux/android.h>
@@ -204,7 +205,7 @@
             }
         };
         ImportKernelCmdline(parser);
-        ImportBootconfig(parser);
+        android::fs_mgr::ImportBootconfig(parser);
         return partition_map;
     }();
 
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 0e82022..3557787 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1351,7 +1351,7 @@
 
 
 static void ProcessBootconfig() {
-    ImportBootconfig([&](const std::string& key, const std::string& value) {
+    android::fs_mgr::ImportBootconfig([&](const std::string& key, const std::string& value) {
         if (StartsWith(key, ANDROIDBOOT_PREFIX)) {
             InitPropertySet("ro.boot." + key.substr(ANDROIDBOOT_PREFIX.size()), value);
         }
diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp
index e6b868e..547b186 100644
--- a/init/reboot_utils.cpp
+++ b/init/reboot_utils.cpp
@@ -27,6 +27,7 @@
 #include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <cutils/android_reboot.h>
+#include <fs_mgr.h>
 #include <unwindstack/AndroidUnwinder.h>
 
 #include "capabilities.h"
@@ -48,13 +49,9 @@
 
     const std::string kInitFatalPanicParamString = "androidboot.init_fatal_panic";
     if (cmdline.find(kInitFatalPanicParamString) == std::string::npos) {
-        init_fatal_panic = false;
-        ImportBootconfig(
-                [kInitFatalPanicParamString](const std::string& key, const std::string& value) {
-                    if (key == kInitFatalPanicParamString && value == "true") {
-                        init_fatal_panic = true;
-                    }
-                });
+        std::string value;
+        init_fatal_panic = (android::fs_mgr::GetBootconfig(kInitFatalPanicParamString, &value) &&
+                            value == "true");
     } else {
         const std::string kInitFatalPanicString = kInitFatalPanicParamString + "=true";
         init_fatal_panic = cmdline.find(kInitFatalPanicString) != std::string::npos;
@@ -68,11 +65,7 @@
     const std::string kRebootTargetString = "androidboot.init_fatal_reboot_target";
     auto start_pos = cmdline.find(kRebootTargetString);
     if (start_pos == std::string::npos) {
-        ImportBootconfig([kRebootTargetString](const std::string& key, const std::string& value) {
-            if (key == kRebootTargetString) {
-                init_fatal_reboot_target = value;
-            }
-        });
+        android::fs_mgr::GetBootconfig(kRebootTargetString, &init_fatal_reboot_target);
         // We already default to bootloader if no setting is provided.
     } else {
         const std::string kRebootTargetStringPattern = kRebootTargetString + "=";
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 51093d8..6fb028b 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -110,11 +110,11 @@
     });
 
     if (status == SELINUX_ENFORCING) {
-        ImportBootconfig([&](const std::string& key, const std::string& value) {
-            if (key == "androidboot.selinux" && value == "permissive") {
-                status = SELINUX_PERMISSIVE;
-            }
-        });
+        std::string value;
+        if (android::fs_mgr::GetBootconfig("androidboot.selinux", &value) &&
+            value == "permissive") {
+            status = SELINUX_PERMISSIVE;
+        }
     }
 
     return status;
diff --git a/init/util.cpp b/init/util.cpp
index 61d59a4..b34d45d 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -254,21 +254,6 @@
     }
 }
 
-void ImportBootconfig(const std::function<void(const std::string&, const std::string&)>& fn) {
-    std::string bootconfig;
-    android::base::ReadFileToString("/proc/bootconfig", &bootconfig);
-
-    for (const auto& entry : android::base::Split(bootconfig, "\n")) {
-        std::vector<std::string> pieces = android::base::Split(entry, "=");
-        if (pieces.size() == 2) {
-            // get rid of the extra space between a list of values and remove the quotes.
-            std::string value = android::base::StringReplace(pieces[1], "\", \"", ",", true);
-            value.erase(std::remove(value.begin(), value.end(), '"'), value.end());
-            fn(android::base::Trim(pieces[0]), android::base::Trim(value));
-        }
-    }
-}
-
 bool make_dir(const std::string& path, mode_t mode) {
     std::string secontext;
     if (SelabelLookupFileContext(path, mode, &secontext) && !secontext.empty()) {
diff --git a/init/util.h b/init/util.h
index 1c00a3e..0b0ef63 100644
--- a/init/util.h
+++ b/init/util.h
@@ -55,7 +55,6 @@
 bool mkdir_recursive(const std::string& pathname, mode_t mode);
 int wait_for_file(const char *filename, std::chrono::nanoseconds timeout);
 void ImportKernelCmdline(const std::function<void(const std::string&, const std::string&)>&);
-void ImportBootconfig(const std::function<void(const std::string&, const std::string&)>&);
 bool make_dir(const std::string& path, mode_t mode);
 bool is_dir(const char* pathname);
 Result<std::string> ExpandProps(const std::string& src);