Add VintfObjectRecovery.

This is a special VintfObject for recovery ramdisk. In
recovery ramdisk, there's no Treble split, and all
manifests are stored under /system/etc/vintf.

Also add vintf_object_recovery_test, which is a host test that
mocks the recovery file system.

Test: vintf_object_recovery_test
Bug: 206888109
Change-Id: Ifc88329832fafaace073dd814fd24b638845f807
diff --git a/VintfObject.cpp b/VintfObject.cpp
index c9460a0..8d9df31 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -30,6 +30,7 @@
 #include <hidl/metadata.h>
 
 #include "CompatibilityMatrix.h"
+#include "VintfObjectUtils.h"
 #include "constants-private.h"
 #include "parse_string.h"
 #include "parse_xml.h"
@@ -50,29 +51,6 @@
 static constexpr bool kIsTarget = false;
 #endif
 
-template <typename T, typename F>
-static std::shared_ptr<const T> Get(const char* id, LockedSharedPtr<T>* ptr,
-                                    const F& fetchAllInformation) {
-    std::unique_lock<std::mutex> _lock(ptr->mutex);
-    if (!ptr->fetchedOnce) {
-        LOG(INFO) << id << ": Reading VINTF information.";
-        ptr->object = std::make_unique<T>();
-        std::string error;
-        status_t status = fetchAllInformation(ptr->object.get(), &error);
-        if (status == OK) {
-            ptr->fetchedOnce = true;
-            LOG(INFO) << id << ": Successfully processed VINTF information";
-        } else {
-            // Doubled because a malformed error std::string might cause us to
-            // lose the status.
-            LOG(ERROR) << id << ": status from fetching VINTF information: " << status;
-            LOG(ERROR) << id << ": " << status << " VINTF parse error: " << error;
-            ptr->object = nullptr;  // frees the old object
-        }
-    }
-    return ptr->object;
-}
-
 static std::unique_ptr<FileSystem> createDefaultFileSystem() {
     std::unique_ptr<FileSystem> fileSystem;
     if (kIsTarget) {
@@ -215,8 +193,9 @@
 }
 
 // Load and combine all of the manifests in a directory
+// If forceSchemaType, all fragment manifests are coerced into manifest->type().
 status_t VintfObject::addDirectoryManifests(const std::string& directory, HalManifest* manifest,
-                                            std::string* error) {
+                                            bool forceSchemaType, std::string* error) {
     std::vector<std::string> fileNames;
     status_t err = getFileSystem()->listFiles(directory, &fileNames, error);
     // if the directory isn't there, that's okay
@@ -235,6 +214,10 @@
         err = fetchOneHalManifest(directory + file, &fragmentManifest, error);
         if (err != OK) return err;
 
+        if (forceSchemaType) {
+            fragmentManifest.setType(manifest->type());
+        }
+
         if (!manifest->addAll(&fragmentManifest, error)) {
             if (error) {
                 error->insert(0, "Cannot add manifest fragment " + directory + file + ": ");
@@ -263,7 +246,8 @@
 
     if (vendorStatus == OK) {
         *out = std::move(vendorManifest);
-        status_t fragmentStatus = addDirectoryManifests(kVendorManifestFragmentDir, out, error);
+        status_t fragmentStatus = addDirectoryManifests(kVendorManifestFragmentDir, out,
+                                                        false /* forceSchemaType*/, error);
         if (fragmentStatus != OK) {
             return fragmentStatus;
         }
@@ -284,13 +268,15 @@
                 return UNKNOWN_ERROR;
             }
         }
-        return addDirectoryManifests(kOdmManifestFragmentDir, out, error);
+        return addDirectoryManifests(kOdmManifestFragmentDir, out, false /* forceSchemaType */,
+                                     error);
     }
 
     // vendorStatus != OK, "out" is not changed.
     if (odmStatus == OK) {
         *out = std::move(odmManifest);
-        return addDirectoryManifests(kOdmManifestFragmentDir, out, error);
+        return addDirectoryManifests(kOdmManifestFragmentDir, out, false /* forceSchemaType */,
+                                     error);
     }
 
     // Use legacy /vendor/manifest.xml
@@ -397,7 +383,8 @@
 status_t VintfObject::fetchUnfilteredFrameworkHalManifest(HalManifest* out, std::string* error) {
     auto systemEtcStatus = fetchOneHalManifest(kSystemManifest, out, error);
     if (systemEtcStatus == OK) {
-        auto dirStatus = addDirectoryManifests(kSystemManifestFragmentDir, out, error);
+        auto dirStatus = addDirectoryManifests(kSystemManifestFragmentDir, out,
+                                               false /* forceSchemaType */, error);
         if (dirStatus != OK) {
             return dirStatus;
         }
@@ -421,7 +408,8 @@
                 }
             }
 
-            auto fragmentStatus = addDirectoryManifests(frags, out, error);
+            auto fragmentStatus =
+                addDirectoryManifests(frags, out, false /* forceSchemaType */, error);
             if (fragmentStatus != OK) {
                 return fragmentStatus;
             }