VintfObject now provides instance methods.
am: 9f78c180ff

Change-Id: Idac69cbf04fa0b5339cf9c9d0bca5dddd05646b4
diff --git a/Android.bp b/Android.bp
index 23dc1bb..3caf684 100644
--- a/Android.bp
+++ b/Android.bp
@@ -30,8 +30,8 @@
     }
 }
 
-cc_library_static {
-    name: "libvintf_common",
+cc_library {
+    name: "libvintf",
     defaults: ["libvintf-defaults"],
     host_supported: true,
     srcs: [
@@ -85,33 +85,6 @@
     }
 }
 
-// libvintf_common + utils.cpp
-cc_library {
-    name: "libvintf",
-    host_supported: true,
-    defaults: ["libvintf-defaults"],
-    shared_libs: [
-        "libbase",
-        "libhidl-gen-utils",
-        "liblog",
-        "libselinux",
-        "libtinyxml2",
-        "libz",
-    ],
-    export_include_dirs: ["include"],
-    local_include_dirs: ["include/vintf"],
-
-    srcs: [
-        "utils.cpp",
-    ],
-
-    export_shared_lib_headers: [
-        "libhidl-gen-utils",
-    ],
-
-    whole_static_libs: ["libvintf_common"],
-}
-
 cc_binary {
     name: "vintf",
     defaults: ["libvintf-defaults"],
@@ -131,7 +104,7 @@
     static_libs: [
         "libbase",
         "libhidl-gen-utils",
-        "libvintf_common",
+        "libvintf",
         "libutils",
         "libtinyxml2",
     ],
diff --git a/CompatibilityMatrix.cpp b/CompatibilityMatrix.cpp
index 8f6a7a8..6a5645c 100644
--- a/CompatibilityMatrix.cpp
+++ b/CompatibilityMatrix.cpp
@@ -52,8 +52,10 @@
     return {1, 0};
 }
 
-status_t CompatibilityMatrix::fetchAllInformation(const std::string& path, std::string* error) {
-    return details::fetchAllInformation(path, gCompatibilityMatrixConverter, this, error);
+status_t CompatibilityMatrix::fetchAllInformation(const FileSystem* fileSystem,
+                                                  const std::string& path, std::string* error) {
+    return details::fetchAllInformation(fileSystem, path, gCompatibilityMatrixConverter, this,
+                                        error);
 }
 
 std::string CompatibilityMatrix::getXmlSchemaPath(const std::string& xmlFileName,
diff --git a/FileSystem.cpp b/FileSystem.cpp
index 5b871ee..e0d09e1 100644
--- a/FileSystem.cpp
+++ b/FileSystem.cpp
@@ -27,28 +27,6 @@
 namespace vintf {
 namespace details {
 
-static std::mutex sFileSystemMutex;
-static std::unique_ptr<FileSystem> sFileSystem{};
-
-bool initFileSystem(std::unique_ptr<FileSystem>&& value) {
-    std::lock_guard<std::mutex> lock(sFileSystemMutex);
-    if (sFileSystem != nullptr) return false;
-    sFileSystem = std::move(value);
-    return true;
-}
-
-FileSystem& getFileSystem() {
-    std::lock_guard<std::mutex> lock(sFileSystemMutex);
-    if (sFileSystem == nullptr) {
-#ifdef LIBVINTF_TARGET
-        sFileSystem = std::make_unique<details::FileSystemImpl>();
-#else
-        sFileSystem = std::make_unique<details::FileSystemNoOp>();
-#endif
-    }
-    return *sFileSystem;
-}
-
 status_t FileSystemImpl::fetch(const std::string& path, std::string* fetched,
                                std::string* error) const {
     std::ifstream in;
diff --git a/HalManifest.cpp b/HalManifest.cpp
index fbb3220..17ab530 100644
--- a/HalManifest.cpp
+++ b/HalManifest.cpp
@@ -360,8 +360,9 @@
     return matrix;
 }
 
-status_t HalManifest::fetchAllInformation(const std::string& path, std::string* error) {
-    return details::fetchAllInformation(path, gHalManifestConverter, this, error);
+status_t HalManifest::fetchAllInformation(const FileSystem* fileSystem, const std::string& path,
+                                          std::string* error) {
+    return details::fetchAllInformation(fileSystem, path, gHalManifestConverter, this, error);
 }
 
 SchemaType HalManifest::type() const {
diff --git a/PropertyFetcher.cpp b/PropertyFetcher.cpp
index 28caee3..d406262 100644
--- a/PropertyFetcher.cpp
+++ b/PropertyFetcher.cpp
@@ -17,24 +17,41 @@
 
 #include "utils.h"
 
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+
 namespace android {
 namespace vintf {
 namespace details {
 
-std::string PropertyFetcher::getProperty(const std::string&,
-                                         const std::string& defaultValue) const {
+std::string PropertyFetcherNoOp::getProperty(const std::string&,
+                                             const std::string& defaultValue) const {
     return defaultValue;
 }
 
-uint64_t PropertyFetcher::getUintProperty(const std::string&, uint64_t,
-                                          uint64_t defaultValue) const {
+uint64_t PropertyFetcherNoOp::getUintProperty(const std::string&, uint64_t,
+                                              uint64_t defaultValue) const {
     return defaultValue;
 }
 
-bool PropertyFetcher::getBoolProperty(const std::string&, bool defaultValue) const {
+bool PropertyFetcherNoOp::getBoolProperty(const std::string&, bool defaultValue) const {
     return defaultValue;
 }
 
+std::string PropertyFetcherImpl::getProperty(const std::string& key,
+                                             const std::string& defaultValue) const {
+    return android::base::GetProperty(key, defaultValue);
+}
+
+uint64_t PropertyFetcherImpl::getUintProperty(const std::string& key, uint64_t defaultValue,
+                                              uint64_t max) const {
+    return android::base::GetUintProperty(key, defaultValue, max);
+}
+
+bool PropertyFetcherImpl::getBoolProperty(const std::string& key, bool defaultValue) const {
+    return android::base::GetBoolProperty(key, defaultValue);
+}
+
 }  // namespace details
 }  // namespace vintf
 }  // namespace android
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 0e757ca..c34f0bb 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -37,18 +37,11 @@
 
 using namespace details;
 
-template <typename T>
-struct LockedSharedPtr {
-    std::shared_ptr<T> object;
-    std::mutex mutex;
-    bool fetchedOnce = false;
-};
-
-struct LockedRuntimeInfoCache {
-    std::shared_ptr<RuntimeInfo> object;
-    std::mutex mutex;
-    RuntimeInfo::FetchFlags fetchedFlags = RuntimeInfo::FetchFlag::NONE;
-};
+#ifdef LIBVINTF_TARGET
+static constexpr bool kIsTarget = true;
+#else
+static constexpr bool kIsTarget = false;
+#endif
 
 template <typename T, typename F>
 static std::shared_ptr<const T> Get(
@@ -68,51 +61,102 @@
     return ptr->object;
 }
 
-// static
+static std::unique_ptr<FileSystem> createDefaultFileSystem() {
+    std::unique_ptr<FileSystem> fileSystem;
+    if (kIsTarget) {
+        fileSystem = std::make_unique<details::FileSystemImpl>();
+    } else {
+        fileSystem = std::make_unique<details::FileSystemNoOp>();
+    }
+    return fileSystem;
+}
+
+static std::unique_ptr<PropertyFetcher> createDefaultPropertyFetcher() {
+    std::unique_ptr<PropertyFetcher> propertyFetcher;
+    if (kIsTarget) {
+        propertyFetcher = std::make_unique<details::PropertyFetcherImpl>();
+    } else {
+        propertyFetcher = std::make_unique<details::PropertyFetcherNoOp>();
+    }
+    return propertyFetcher;
+}
+
+VintfObject::VintfObject(std::unique_ptr<FileSystem>&& fileSystem,
+                         std::unique_ptr<details::PartitionMounter>&& partitionMounter,
+                         std::unique_ptr<details::ObjectFactory<RuntimeInfo>>&& runtimeInfoFactory,
+                         std::unique_ptr<details::PropertyFetcher>&& propertyFetcher)
+    : mFileSystem(fileSystem ? std::move(fileSystem) : createDefaultFileSystem()),
+      mPartitionMounter(partitionMounter ? std::move(partitionMounter)
+                                         : std::make_unique<details::PartitionMounter>()),
+      mRuntimeInfoFactory(runtimeInfoFactory
+                              ? std::move(runtimeInfoFactory)
+                              : std::make_unique<details::ObjectFactory<RuntimeInfo>>()),
+      mPropertyFetcher(propertyFetcher ? std::move(propertyFetcher)
+                                       : createDefaultPropertyFetcher()) {}
+
+details::LockedSharedPtr<VintfObject> VintfObject::sInstance{};
+std::shared_ptr<VintfObject> VintfObject::GetInstance() {
+    std::unique_lock<std::mutex> lock(sInstance.mutex);
+    if (sInstance.object == nullptr) {
+        sInstance.object = std::make_shared<VintfObject>();
+    }
+    return sInstance.object;
+}
+
 std::shared_ptr<const HalManifest> VintfObject::GetDeviceHalManifest(bool skipCache) {
-    static LockedSharedPtr<HalManifest> gVendorManifest;
-    return Get(&gVendorManifest, skipCache, &VintfObject::FetchDeviceHalManifest);
+    return GetInstance()->getDeviceHalManifest(skipCache);
 }
 
-// static
+std::shared_ptr<const HalManifest> VintfObject::getDeviceHalManifest(bool skipCache) {
+    return Get(&mDeviceManifest, skipCache,
+               std::bind(&VintfObject::fetchDeviceHalManifest, this, _1, _2));
+}
+
 std::shared_ptr<const HalManifest> VintfObject::GetFrameworkHalManifest(bool skipCache) {
-    static LockedSharedPtr<HalManifest> gFrameworkManifest;
-    return Get(&gFrameworkManifest, skipCache, &VintfObject::FetchFrameworkHalManifest);
+    return GetInstance()->getFrameworkHalManifest(skipCache);
 }
 
+std::shared_ptr<const HalManifest> VintfObject::getFrameworkHalManifest(bool skipCache) {
+    return Get(&mFrameworkManifest, skipCache,
+               std::bind(&VintfObject::fetchFrameworkHalManifest, this, _1, _2));
+}
 
-// static
 std::shared_ptr<const CompatibilityMatrix> VintfObject::GetDeviceCompatibilityMatrix(bool skipCache) {
-    static LockedSharedPtr<CompatibilityMatrix> gDeviceMatrix;
-    return Get(&gDeviceMatrix, skipCache, &VintfObject::FetchDeviceMatrix);
+    return GetInstance()->getDeviceCompatibilityMatrix(skipCache);
 }
 
-// static
+std::shared_ptr<const CompatibilityMatrix> VintfObject::getDeviceCompatibilityMatrix(
+    bool skipCache) {
+    return Get(&mDeviceMatrix, skipCache, std::bind(&VintfObject::fetchDeviceMatrix, this, _1, _2));
+}
+
 std::shared_ptr<const CompatibilityMatrix> VintfObject::GetFrameworkCompatibilityMatrix(bool skipCache) {
-    static LockedSharedPtr<CompatibilityMatrix> gFrameworkMatrix;
-    static LockedSharedPtr<CompatibilityMatrix> gCombinedFrameworkMatrix;
-    static std::mutex gFrameworkCompatibilityMatrixMutex;
+    return GetInstance()->getFrameworkCompatibilityMatrix(skipCache);
+}
 
+std::shared_ptr<const CompatibilityMatrix> VintfObject::getFrameworkCompatibilityMatrix(
+    bool skipCache) {
     // To avoid deadlock, get device manifest before any locks.
-    auto deviceManifest = GetDeviceHalManifest();
+    auto deviceManifest = getDeviceHalManifest();
 
-    std::unique_lock<std::mutex> _lock(gFrameworkCompatibilityMatrixMutex);
+    std::unique_lock<std::mutex> _lock(mFrameworkCompatibilityMatrixMutex);
 
     auto combined =
-        Get(&gCombinedFrameworkMatrix, skipCache,
-            std::bind(&VintfObject::GetCombinedFrameworkMatrix, deviceManifest, _1, _2));
+        Get(&mCombinedFrameworkMatrix, skipCache,
+            std::bind(&VintfObject::getCombinedFrameworkMatrix, this, deviceManifest, _1, _2));
     if (combined != nullptr) {
         return combined;
     }
 
-    return Get(&gFrameworkMatrix, skipCache,
-               std::bind(&CompatibilityMatrix::fetchAllInformation, _1, kSystemLegacyMatrix, _2));
+    return Get(&mFrameworkMatrix, skipCache,
+               std::bind(&CompatibilityMatrix::fetchAllInformation, _1, mFileSystem.get(),
+                         kSystemLegacyMatrix, _2));
 }
 
-status_t VintfObject::GetCombinedFrameworkMatrix(
+status_t VintfObject::getCombinedFrameworkMatrix(
     const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out,
     std::string* error) {
-    auto matrixFragments = GetAllFrameworkMatrixLevels(error);
+    auto matrixFragments = getAllFrameworkMatrixLevels(error);
     if (matrixFragments.empty()) {
         return NAME_NOT_FOUND;
     }
@@ -125,7 +169,7 @@
 
     // TODO(b/70628538): Do not infer from Shipping API level.
     if (deviceLevel == Level::UNSPECIFIED) {
-        auto shippingApi = getPropertyFetcher().getUintProperty("ro.product.first_api_level", 0u);
+        auto shippingApi = mPropertyFetcher->getUintProperty("ro.product.first_api_level", 0u);
         if (shippingApi != 0u) {
             deviceLevel = details::convertFromApiLevel(shippingApi);
         }
@@ -162,10 +206,10 @@
 }
 
 // Load and combine all of the manifests in a directory
-status_t VintfObject::AddDirectoryManifests(const std::string& directory, HalManifest* manifest,
+status_t VintfObject::addDirectoryManifests(const std::string& directory, HalManifest* manifest,
                                             std::string* error) {
     std::vector<std::string> fileNames;
-    status_t err = details::getFileSystem().listFiles(directory, &fileNames, error);
+    status_t err = mFileSystem->listFiles(directory, &fileNames, error);
     // if the directory isn't there, that's okay
     if (err == NAME_NOT_FOUND) return OK;
     if (err != OK) return err;
@@ -174,7 +218,7 @@
         // Only adds HALs because all other things are added by libvintf
         // itself for now.
         HalManifest fragmentManifest;
-        err = FetchOneHalManifest(directory + file, &fragmentManifest, error);
+        err = fetchOneHalManifest(directory + file, &fragmentManifest, error);
         if (err != OK) return err;
 
         manifest->addAllHals(&fragmentManifest);
@@ -190,21 +234,21 @@
 // 4. /vendor/manifest.xml (legacy, no fragments)
 // where:
 // A + B means adding <hal> tags from B to A (so that <hal>s from B can override A)
-status_t VintfObject::FetchDeviceHalManifest(HalManifest* out, std::string* error) {
-    status_t vendorStatus = FetchOneHalManifest(kVendorManifest, out, error);
+status_t VintfObject::fetchDeviceHalManifest(HalManifest* out, std::string* error) {
+    status_t vendorStatus = fetchOneHalManifest(kVendorManifest, out, error);
     if (vendorStatus != OK && vendorStatus != NAME_NOT_FOUND) {
         return vendorStatus;
     }
 
     if (vendorStatus == OK) {
-        status_t fragmentStatus = AddDirectoryManifests(kVendorManifestFragmentDir, out, error);
+        status_t fragmentStatus = addDirectoryManifests(kVendorManifestFragmentDir, out, error);
         if (fragmentStatus != OK) {
             return fragmentStatus;
         }
     }
 
     HalManifest odmManifest;
-    status_t odmStatus = FetchOdmHalManifest(&odmManifest, error);
+    status_t odmStatus = fetchOdmHalManifest(&odmManifest, error);
     if (odmStatus != OK && odmStatus != NAME_NOT_FOUND) {
         return odmStatus;
     }
@@ -213,17 +257,17 @@
         if (odmStatus == OK) {
             out->addAllHals(&odmManifest);
         }
-        return AddDirectoryManifests(kOdmManifestFragmentDir, out, error);
+        return addDirectoryManifests(kOdmManifestFragmentDir, out, error);
     }
 
     // vendorStatus != OK, "out" is not changed.
     if (odmStatus == OK) {
         *out = std::move(odmManifest);
-        return AddDirectoryManifests(kOdmManifestFragmentDir, out, error);
+        return addDirectoryManifests(kOdmManifestFragmentDir, out, error);
     }
 
     // Use legacy /vendor/manifest.xml
-    return out->fetchAllInformation(kVendorLegacyManifest, error);
+    return out->fetchAllInformation(mFileSystem.get(), kVendorLegacyManifest, error);
 }
 
 // "out" is written to iff return status is OK.
@@ -234,34 +278,34 @@
 // 4. /odm/etc/manifest.xml
 // where:
 // {sku} is the value of ro.boot.product.hardware.sku
-status_t VintfObject::FetchOdmHalManifest(HalManifest* out, std::string* error) {
+status_t VintfObject::fetchOdmHalManifest(HalManifest* out, std::string* error) {
     status_t status;
 
     std::string productModel;
-    productModel = getPropertyFetcher().getProperty("ro.boot.product.hardware.sku", "");
+    productModel = mPropertyFetcher->getProperty("ro.boot.product.hardware.sku", "");
 
     if (!productModel.empty()) {
         status =
-            FetchOneHalManifest(kOdmVintfDir + "manifest_" + productModel + ".xml", out, error);
+            fetchOneHalManifest(kOdmVintfDir + "manifest_" + productModel + ".xml", out, error);
         if (status == OK || status != NAME_NOT_FOUND) {
             return status;
         }
     }
 
-    status = FetchOneHalManifest(kOdmManifest, out, error);
+    status = fetchOneHalManifest(kOdmManifest, out, error);
     if (status == OK || status != NAME_NOT_FOUND) {
         return status;
     }
 
     if (!productModel.empty()) {
-        status = FetchOneHalManifest(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml", out,
+        status = fetchOneHalManifest(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml", out,
                                      error);
         if (status == OK || status != NAME_NOT_FOUND) {
             return status;
         }
     }
 
-    status = FetchOneHalManifest(kOdmLegacyManifest, out, error);
+    status = fetchOneHalManifest(kOdmLegacyManifest, out, error);
     if (status == OK || status != NAME_NOT_FOUND) {
         return status;
     }
@@ -271,40 +315,40 @@
 
 // Fetch one manifest.xml file. "out" is written to iff return status is OK.
 // Returns NAME_NOT_FOUND if file is missing.
-status_t VintfObject::FetchOneHalManifest(const std::string& path, HalManifest* out,
+status_t VintfObject::fetchOneHalManifest(const std::string& path, HalManifest* out,
                                           std::string* error) {
     HalManifest ret;
-    status_t status = ret.fetchAllInformation(path, error);
+    status_t status = ret.fetchAllInformation(mFileSystem.get(), path, error);
     if (status == OK) {
         *out = std::move(ret);
     }
     return status;
 }
 
-status_t VintfObject::FetchDeviceMatrix(CompatibilityMatrix* out, std::string* error) {
+status_t VintfObject::fetchDeviceMatrix(CompatibilityMatrix* out, std::string* error) {
     CompatibilityMatrix etcMatrix;
-    if (etcMatrix.fetchAllInformation(kVendorMatrix, error) == OK) {
+    if (etcMatrix.fetchAllInformation(mFileSystem.get(), kVendorMatrix, error) == OK) {
         *out = std::move(etcMatrix);
         return OK;
     }
-    return out->fetchAllInformation(kVendorLegacyMatrix, error);
+    return out->fetchAllInformation(mFileSystem.get(), kVendorLegacyMatrix, error);
 }
 
-status_t VintfObject::FetchFrameworkHalManifest(HalManifest* out, std::string* error) {
+status_t VintfObject::fetchFrameworkHalManifest(HalManifest* out, std::string* error) {
     HalManifest etcManifest;
-    if (etcManifest.fetchAllInformation(kSystemManifest, error) == OK) {
+    if (etcManifest.fetchAllInformation(mFileSystem.get(), kSystemManifest, error) == OK) {
         *out = std::move(etcManifest);
-        return AddDirectoryManifests(kSystemManifestFragmentDir, out, error);
+        return addDirectoryManifests(kSystemManifestFragmentDir, out, error);
     }
-    return out->fetchAllInformation(kSystemLegacyManifest, error);
+    return out->fetchAllInformation(mFileSystem.get(), kSystemLegacyManifest, error);
 }
 
-std::vector<Named<CompatibilityMatrix>> VintfObject::GetAllFrameworkMatrixLevels(
+std::vector<Named<CompatibilityMatrix>> VintfObject::getAllFrameworkMatrixLevels(
     std::string* error) {
     std::vector<std::string> fileNames;
     std::vector<Named<CompatibilityMatrix>> results;
 
-    if (details::getFileSystem().listFiles(kSystemVintfDir, &fileNames, error) != OK) {
+    if (mFileSystem->listFiles(kSystemVintfDir, &fileNames, error) != OK) {
         return {};
     }
     for (const std::string& fileName : fileNames) {
@@ -312,7 +356,7 @@
 
         std::string content;
         std::string fetchError;
-        status_t status = details::getFileSystem().fetch(path, &content, &fetchError);
+        status_t status = mFileSystem->fetch(path, &content, &fetchError);
         if (status != OK) {
             if (error) {
                 *error += "Framework Matrix: Ignore file " + path + ": " + fetchError + "\n";
@@ -345,28 +389,30 @@
     return results;
 }
 
-// static
 std::shared_ptr<const RuntimeInfo> VintfObject::GetRuntimeInfo(bool skipCache,
                                                                RuntimeInfo::FetchFlags flags) {
-    static LockedRuntimeInfoCache gDeviceRuntimeInfo;
-    std::unique_lock<std::mutex> _lock(gDeviceRuntimeInfo.mutex);
+    return GetInstance()->getRuntimeInfo(skipCache, flags);
+}
+std::shared_ptr<const RuntimeInfo> VintfObject::getRuntimeInfo(bool skipCache,
+                                                               RuntimeInfo::FetchFlags flags) {
+    std::unique_lock<std::mutex> _lock(mDeviceRuntimeInfo.mutex);
 
     if (!skipCache) {
-        flags &= (~gDeviceRuntimeInfo.fetchedFlags);
+        flags &= (~mDeviceRuntimeInfo.fetchedFlags);
     }
 
-    if (gDeviceRuntimeInfo.object == nullptr) {
-        gDeviceRuntimeInfo.object = details::gRuntimeInfoFactory->make_shared();
+    if (mDeviceRuntimeInfo.object == nullptr) {
+        mDeviceRuntimeInfo.object = mRuntimeInfoFactory->make_shared();
     }
 
-    status_t status = gDeviceRuntimeInfo.object->fetchAllInformation(flags);
+    status_t status = mDeviceRuntimeInfo.object->fetchAllInformation(flags);
     if (status != OK) {
-        gDeviceRuntimeInfo.fetchedFlags &= (~flags);  // mark the fields as "not fetched"
+        mDeviceRuntimeInfo.fetchedFlags &= (~flags);  // mark the fields as "not fetched"
         return nullptr;
     }
 
-    gDeviceRuntimeInfo.fetchedFlags |= flags;
-    return gDeviceRuntimeInfo.object;
+    mDeviceRuntimeInfo.fetchedFlags |= flags;
+    return mDeviceRuntimeInfo.object;
 }
 
 namespace details {
@@ -449,12 +495,13 @@
     std::shared_ptr<const RuntimeInfo> runtimeInfo;
 };
 
+}  // namespace details
+
 // Checks given compatibility info against info on the device. If no
 // compatability info is given then the device info will be checked against
 // itself.
-int32_t checkCompatibility(const std::vector<std::string>& xmls, bool mount,
-                           const PartitionMounter& mounter, std::string* error,
-                           DisabledChecks disabledChecks) {
+int32_t VintfObject::checkCompatibility(const std::vector<std::string>& xmls, bool mount,
+                                        std::string* error, DisabledChecks disabledChecks) {
     status_t status;
     ParseStatus parseStatus;
     PackageInfo pkg; // All information from package.
@@ -484,37 +531,36 @@
 
     // get missing info from device
     // use functions instead of std::bind because std::bind doesn't work well with mock objects
-    auto mountSystem = [&mounter] { return mounter.mountSystem(); };
-    auto mountVendor = [&mounter] { return mounter.mountVendor(); };
+    auto mountSystem = [this] { return this->mPartitionMounter->mountSystem(); };
+    auto mountVendor = [this] { return this->mPartitionMounter->mountVendor(); };
     if ((status = getMissing(
              pkg.fwk.manifest, mount, mountSystem, &updated.fwk.manifest,
-             std::bind(VintfObject::GetFrameworkHalManifest, true /* skipCache */))) != OK) {
+             std::bind(&VintfObject::getFrameworkHalManifest, this, true /* skipCache */))) != OK) {
         return status;
     }
     if ((status = getMissing(
              pkg.dev.manifest, mount, mountVendor, &updated.dev.manifest,
-             std::bind(VintfObject::GetDeviceHalManifest, true /* skipCache */))) != OK) {
+             std::bind(&VintfObject::getDeviceHalManifest, this, true /* skipCache */))) != OK) {
         return status;
     }
-    if ((status = getMissing(
-             pkg.fwk.matrix, mount, mountSystem, &updated.fwk.matrix,
-             std::bind(VintfObject::GetFrameworkCompatibilityMatrix, true /* skipCache */))) !=
-        OK) {
+    if ((status = getMissing(pkg.fwk.matrix, mount, mountSystem, &updated.fwk.matrix,
+                             std::bind(&VintfObject::getFrameworkCompatibilityMatrix, this,
+                                       true /* skipCache */))) != OK) {
         return status;
     }
-    if ((status = getMissing(
-             pkg.dev.matrix, mount, mountVendor, &updated.dev.matrix,
-             std::bind(VintfObject::GetDeviceCompatibilityMatrix, true /* skipCache */))) != OK) {
+    if ((status = getMissing(pkg.dev.matrix, mount, mountVendor, &updated.dev.matrix,
+                             std::bind(&VintfObject::getDeviceCompatibilityMatrix, this,
+                                       true /* skipCache */))) != OK) {
         return status;
     }
 
     if (mount) {
-        (void)mounter.umountSystem(); // ignore errors
-        (void)mounter.umountVendor(); // ignore errors
+        (void)mPartitionMounter->umountSystem();  // ignore errors
+        (void)mPartitionMounter->umountVendor();  // ignore errors
     }
 
     if ((disabledChecks & DISABLE_RUNTIME_INFO) == 0) {
-        updated.runtimeInfo = VintfObject::GetRuntimeInfo(true /* skipCache */);
+        updated.runtimeInfo = getRuntimeInfo(true /* skipCache */);
     }
 
     // null checks for files and runtime info after the update
@@ -571,6 +617,8 @@
     return COMPATIBLE;
 }
 
+namespace details {
+
 const std::string kSystemVintfDir = "/system/etc/vintf/";
 const std::string kVendorVintfDir = "/vendor/etc/vintf/";
 const std::string kOdmVintfDir = "/odm/etc/vintf/";
@@ -599,21 +647,24 @@
     };
 }
 
-} // namespace details
+}  // namespace details
 
-// static
 int32_t VintfObject::CheckCompatibility(const std::vector<std::string>& xmls, std::string* error,
                                         DisabledChecks disabledChecks) {
-    return details::checkCompatibility(xmls, false /* mount */, *details::gPartitionMounter, error,
-                                       disabledChecks);
+    return GetInstance()->checkCompatibility(xmls, error, disabledChecks);
 }
 
-bool VintfObject::isHalDeprecated(const MatrixHal& oldMatrixHal,
+int32_t VintfObject::checkCompatibility(const std::vector<std::string>& xmls, std::string* error,
+                                        DisabledChecks disabledChecks) {
+    return checkCompatibility(xmls, false /* mount */, error, disabledChecks);
+}
+
+bool VintfObject::IsHalDeprecated(const MatrixHal& oldMatrixHal,
                                   const CompatibilityMatrix& targetMatrix,
                                   const ListInstances& listInstances, std::string* error) {
     bool isDeprecated = false;
     oldMatrixHal.forEachInstance([&](const MatrixInstance& oldMatrixInstance) {
-        if (isInstanceDeprecated(oldMatrixInstance, targetMatrix, listInstances, error)) {
+        if (IsInstanceDeprecated(oldMatrixInstance, targetMatrix, listInstances, error)) {
             isDeprecated = true;
         }
         return !isDeprecated;  // continue if no deprecated instance is found.
@@ -627,7 +678,7 @@
 // 1. package@x.?::interface/servedInstance is not in targetMatrix; OR
 // 2. package@x.z::interface/servedInstance is in targetMatrix but
 //    servedInstance is not in listInstances(package@x.z::interface)
-bool VintfObject::isInstanceDeprecated(const MatrixInstance& oldMatrixInstance,
+bool VintfObject::IsInstanceDeprecated(const MatrixInstance& oldMatrixInstance,
                                        const CompatibilityMatrix& targetMatrix,
                                        const ListInstances& listInstances, std::string* error) {
     const std::string& package = oldMatrixInstance.package();
@@ -692,13 +743,16 @@
 }
 
 int32_t VintfObject::CheckDeprecation(const ListInstances& listInstances, std::string* error) {
-    auto matrixFragments = GetAllFrameworkMatrixLevels(error);
+    return GetInstance()->checkDeprecation(listInstances, error);
+}
+int32_t VintfObject::checkDeprecation(const ListInstances& listInstances, std::string* error) {
+    auto matrixFragments = getAllFrameworkMatrixLevels(error);
     if (matrixFragments.empty()) {
         if (error && error->empty())
             *error = "Cannot get framework matrix for each FCM version for unknown error.";
         return NAME_NOT_FOUND;
     }
-    auto deviceManifest = GetDeviceHalManifest();
+    auto deviceManifest = getDeviceHalManifest();
     if (deviceManifest == nullptr) {
         if (error) *error = "No device manifest.";
         return NAME_NOT_FOUND;
@@ -728,7 +782,7 @@
 
         const auto& oldMatrix = namedMatrix.object;
         for (const MatrixHal& hal : oldMatrix.getHals()) {
-            hasDeprecatedHals |= isHalDeprecated(hal, *targetMatrix, listInstances, error);
+            hasDeprecatedHals |= IsHalDeprecated(hal, *targetMatrix, listInstances, error);
         }
     }
 
@@ -736,8 +790,11 @@
 }
 
 int32_t VintfObject::CheckDeprecation(std::string* error) {
+    return GetInstance()->checkDeprecation(error);
+}
+int32_t VintfObject::checkDeprecation(std::string* error) {
     using namespace std::placeholders;
-    auto deviceManifest = GetDeviceHalManifest();
+    auto deviceManifest = getDeviceHalManifest();
     ListInstances inManifest =
         [&deviceManifest](const std::string& package, Version version, const std::string& interface,
                           const std::vector<std::string>& /* hintInstances */) {
@@ -750,11 +807,23 @@
                 });
             return ret;
         };
-    return CheckDeprecation(inManifest, error);
+    return checkDeprecation(inManifest, error);
 }
 
-bool VintfObject::InitFileSystem(std::unique_ptr<FileSystem>&& fileSystem) {
-    return details::initFileSystem(std::move(fileSystem));
+const std::unique_ptr<FileSystem>& VintfObject::getFileSystem() {
+    return mFileSystem;
+}
+
+const std::unique_ptr<PartitionMounter>& VintfObject::getPartitionMounter() {
+    return mPartitionMounter;
+}
+
+const std::unique_ptr<PropertyFetcher>& VintfObject::getPropertyFetcher() {
+    return mPropertyFetcher;
+}
+
+const std::unique_ptr<details::ObjectFactory<RuntimeInfo>>& VintfObject::getRuntimeInfoFactory() {
+    return mRuntimeInfoFactory;
 }
 
 } // namespace vintf
diff --git a/VintfObjectRecovery.cpp b/VintfObjectRecovery.cpp
index 9d7cab7..9efb318 100644
--- a/VintfObjectRecovery.cpp
+++ b/VintfObjectRecovery.cpp
@@ -42,12 +42,14 @@
 
 class RecoveryPartitionMounter : public PartitionMounter {
    public:
+    RecoveryPartitionMounter(PropertyFetcher* propertyFetcher)
+        : mPropertyFetcher(propertyFetcher) {}
     status_t mountSystem() const override {
         FstabMgr fstab = defaultFstabMgr();
         if (fstab == NULL) {
             return UNKNOWN_ERROR;
         }
-        if (getPropertyFetcher().getBoolProperty("ro.build.system_root_image", false)) {
+        if (mPropertyFetcher->getBoolProperty("ro.build.system_root_image", false)) {
             return mountAt(fstab, "/", "/system_root");
         } else {
             return mountAt(fstab, "/system", "/system");
@@ -63,7 +65,7 @@
     }
 
     status_t umountSystem() const override {
-        if (getPropertyFetcher().getBoolProperty("ro.build.system_root_image", false)) {
+        if (mPropertyFetcher->getBoolProperty("ro.build.system_root_image", false)) {
             return umount("/system_root");
         } else {
             return umount("/system");
@@ -73,6 +75,9 @@
     status_t umountVendor() const override {
         return umount("/vendor");
     }
+
+   private:
+    PropertyFetcher* mPropertyFetcher{nullptr};
 };
 
 } // namespace details
@@ -80,8 +85,12 @@
 // static
 int32_t VintfObjectRecovery::CheckCompatibility(
         const std::vector<std::string> &xmls, std::string *error) {
-    static details::RecoveryPartitionMounter mounter;
-    return details::checkCompatibility(xmls, true /* mount */, mounter, error);
+    auto propertyFetcher = std::make_unique<details::PropertyFetcherImpl>();
+    auto mounter = std::make_unique<details::RecoveryPartitionMounter>(propertyFetcher.get());
+    auto vintfObject = std::make_unique<VintfObject>(nullptr /* fileSystem */, std::move(mounter),
+                                                     nullptr /* runtime info factory */,
+                                                     std::move(propertyFetcher));
+    return vintfObject->checkCompatibility(xmls, true /* mount */, error);
 }
 
 
diff --git a/check_vintf.cpp b/check_vintf.cpp
index c85cbe3..e4941bd 100644
--- a/check_vintf.cpp
+++ b/check_vintf.cpp
@@ -107,24 +107,13 @@
     std::map<std::string, std::string> mProps;
 };
 
-// globals
-static PartitionMounter partitionMounter;
-PartitionMounter* gPartitionMounter = &partitionMounter;
-
-static ObjectFactory<RuntimeInfo> runtimeInfoFactory;
-ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = &runtimeInfoFactory;
-
-static PresetPropertyFetcher hostPropertyFetcher;
-const PropertyFetcher& getPropertyFetcher() {
-    return hostPropertyFetcher;
-}
-
 // helper functions
 template <typename T>
-std::unique_ptr<T> readObject(const std::string& path, const XmlConverter<T>& converter) {
+std::unique_ptr<T> readObject(FileSystem* fileSystem, const std::string& path,
+                              const XmlConverter<T>& converter) {
     std::string xml;
     std::string error;
-    status_t err = details::getFileSystem().fetch(path, &xml, &error);
+    status_t err = fileSystem->fetch(path, &xml, &error);
     if (err != OK) {
         std::cerr << "Error: Cannot read '" << path << "' (" << strerror(-err) << "): " << error
                   << std::endl;
@@ -139,13 +128,9 @@
 }
 
 int checkCompatibilityForFiles(const std::string& manifestPath, const std::string& matrixPath) {
-    if (!VintfObject::InitFileSystem(std::make_unique<FileSystemImpl>())) {
-        std::cerr << "Cannot initialize FileSystem object." << std::endl;
-        return NO_INIT;
-    }
-
-    auto manifest = readObject(manifestPath, gHalManifestConverter);
-    auto matrix = readObject(matrixPath, gCompatibilityMatrixConverter);
+    auto fileSystem = std::make_unique<FileSystemImpl>();
+    auto manifest = readObject(fileSystem.get(), manifestPath, gHalManifestConverter);
+    auto matrix = readObject(fileSystem.get(), matrixPath, gCompatibilityMatrixConverter);
     if (manifest == nullptr || matrix == nullptr) {
         return -1;
     }
@@ -240,13 +225,12 @@
 }
 
 int checkAllFiles(const std::string& rootdir, const Properties& props, std::string* error) {
-    if (!VintfObject::InitFileSystem(std::make_unique<HostFileSystem>(rootdir))) {
-        std::cerr << "Cannot initialize FileSystem object." << std::endl;
-        return NO_INIT;
-    }
-    hostPropertyFetcher.setProperties(props);
-
-    return VintfObject::CheckCompatibility({} /* packageInfo */, error, DISABLE_RUNTIME_INFO);
+    auto hostPropertyFetcher = std::make_unique<PresetPropertyFetcher>();
+    hostPropertyFetcher->setProperties(props);
+    VintfObject vintfObject(std::make_unique<HostFileSystem>(rootdir),
+                            nullptr /* partition mounter */, nullptr /* runtime info factory */,
+                            std::move(hostPropertyFetcher));
+    return vintfObject.checkCompatibility({} /* packageInfo */, error, DISABLE_RUNTIME_INFO);
 }
 
 }  // namespace details
diff --git a/include/vintf/CompatibilityMatrix.h b/include/vintf/CompatibilityMatrix.h
index 9dd94b8..5c1d496 100644
--- a/include/vintf/CompatibilityMatrix.h
+++ b/include/vintf/CompatibilityMatrix.h
@@ -22,6 +22,7 @@
 
 #include <utils/Errors.h>
 
+#include "FileSystem.h"
 #include "HalGroup.h"
 #include "Level.h"
 #include "MapValueIterator.h"
@@ -80,7 +81,8 @@
     // Similar to addAllHalsAsOptional but on <kernel> entries.
     bool addAllKernelsAsOptional(CompatibilityMatrix* other, std::string* error);
 
-    status_t fetchAllInformation(const std::string& path, std::string* error = nullptr);
+    status_t fetchAllInformation(const FileSystem* fileSystem, const std::string& path,
+                                 std::string* error = nullptr);
 
     // Combine a subset of "matrices". For each CompatibilityMatrix in matrices,
     // - If level() == UNSPECIFIED, use it as the base matrix (for non-HAL, non-XML-file
diff --git a/include/vintf/FileSystem.h b/include/vintf/FileSystem.h
index 202557d..b6cc087 100644
--- a/include/vintf/FileSystem.h
+++ b/include/vintf/FileSystem.h
@@ -19,10 +19,10 @@
 
 #include <memory>
 #include <mutex>
+#include <string>
+#include <vector>
 
 #include <utils/Errors.h>
-#include <vintf/RuntimeInfo.h>
-#include <vintf/parse_xml.h>
 
 namespace android {
 namespace vintf {
@@ -47,15 +47,6 @@
 
 namespace details {
 
-// Initialize the global instance.
-__attribute__((warn_unused_result)) bool initFileSystem(std::unique_ptr<FileSystem>&& value);
-
-// Return the instance provided through init(), or a default implementation
-// if init() is not called. The default implementation queries the actual
-// file system on the device and does nothing on host.
-// Once get(), cannot be init()-ed again.
-FileSystem& getFileSystem();
-
 // Class that actually queries the file system.
 class FileSystemImpl : public FileSystem {
    public:
diff --git a/include/vintf/HalManifest.h b/include/vintf/HalManifest.h
index b72c1b2..9b88c6a 100644
--- a/include/vintf/HalManifest.h
+++ b/include/vintf/HalManifest.h
@@ -23,6 +23,7 @@
 #include <string>
 #include <vector>
 
+#include "FileSystem.h"
 #include "HalGroup.h"
 #include "Level.h"
 #include "ManifestHal.h"
@@ -138,7 +139,8 @@
     friend std::string dump(const HalManifest &vm);
     friend bool operator==(const HalManifest &lft, const HalManifest &rgt);
 
-    status_t fetchAllInformation(const std::string& path, std::string* error = nullptr);
+    status_t fetchAllInformation(const FileSystem* fileSystem, const std::string& path,
+                                 std::string* error = nullptr);
 
     details::Instances expandInstances(const std::string& name) const;
     // Check if all instances in matrixHal is supported in this manifest.
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index 875a25a..6b2394d 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -28,6 +28,33 @@
 
 namespace android {
 namespace vintf {
+
+namespace details {
+class PartitionMounter;
+template <typename T>
+class ObjectFactory;
+class PropertyFetcher;
+
+template <typename T>
+struct LockedSharedPtr {
+    std::shared_ptr<T> object;
+    std::mutex mutex;
+    bool fetchedOnce = false;
+};
+
+struct LockedRuntimeInfoCache {
+    std::shared_ptr<RuntimeInfo> object;
+    std::mutex mutex;
+    RuntimeInfo::FetchFlags fetchedFlags = RuntimeInfo::FetchFlag::NONE;
+};
+}  // namespace details
+
+namespace testing {
+class VintfObjectTestBase;
+class VintfObjectRuntimeInfoTest;
+class VintfObjectCompatibleTest;
+}  // namespace testing
+
 /*
  * The top level class for libvintf.
  * An overall diagram of the public API:
@@ -51,7 +78,155 @@
  * again from the device.
  */
 class VintfObject {
-public:
+   public:
+    /**
+     * A VintfObject that fetches from root and cache results, unless skipCache is specified.
+     * Dependencies can be injected via arguments. If nullptr is provided, the default behavior
+     * is used.
+     * - FileSystem fetch from "/" for target and fetch no files for host
+     * - PartitionMounter does nothing for both target and host
+     * - ObjectFactory<RuntimeInfo> fetches default RuntimeInfo for target and nothing for host
+     * - PropertyFetcher fetches properties for target and nothing for host
+     */
+    VintfObject(std::unique_ptr<FileSystem>&& = nullptr,
+                std::unique_ptr<details::PartitionMounter>&& = nullptr,
+                std::unique_ptr<details::ObjectFactory<RuntimeInfo>>&& = nullptr,
+                std::unique_ptr<details::PropertyFetcher>&& = nullptr);
+
+    /*
+     * Return the API that access the device-side HAL manifest stored
+     * in /vendor/manifest.xml.
+     */
+    std::shared_ptr<const HalManifest> getDeviceHalManifest(bool skipCache = false);
+
+    /*
+     * Return the API that access the framework-side HAL manifest stored
+     * in /system/manfiest.xml.
+     */
+    std::shared_ptr<const HalManifest> getFrameworkHalManifest(bool skipCache = false);
+
+    /*
+     * Return the API that access the device-side compatibility matrix stored
+     * in /vendor/compatibility_matrix.xml.
+     */
+    std::shared_ptr<const CompatibilityMatrix> getDeviceCompatibilityMatrix(bool skipCache = false);
+
+    /*
+     * Return the API that access the framework-side compatibility matrix stored
+     * in /system/compatibility_matrix.xml.
+     */
+    std::shared_ptr<const CompatibilityMatrix> getFrameworkCompatibilityMatrix(
+        bool skipCache = false);
+
+    /*
+     * Return the API that access device runtime info.
+     *
+     * {skipCache == true, flags == ALL}: re-fetch everything
+     * {skipCache == false, flags == ALL}: fetch everything if not previously fetched
+     * {skipCache == true, flags == selected info}: re-fetch selected information
+     *                                if not previously fetched.
+     * {skipCache == false, flags == selected info}: fetch selected information
+     *                                if not previously fetched.
+     *
+     * @param skipCache do not fetch if previously fetched
+     * @param flags bitwise-or of RuntimeInfo::FetchFlag
+     */
+    std::shared_ptr<const RuntimeInfo> getRuntimeInfo(
+        bool skipCache = false, RuntimeInfo::FetchFlags flags = RuntimeInfo::FetchFlag::ALL);
+
+    /**
+     * Check compatibility, given a set of manifests / matrices in packageInfo.
+     * They will be checked against the manifests / matrices on the device.
+     *
+     * @param packageInfo a list of XMLs of HalManifest /
+     * CompatibilityMatrix objects.
+     * @param error error message
+     * @param disabledChecks flags to disable certain checks. See DisabledChecks.
+     *
+     * @return = 0 if success (compatible)
+     *         > 0 if incompatible
+     *         < 0 if any error (mount partition fails, illformed XML, etc.)
+     */
+    int32_t checkCompatibility(const std::vector<std::string>& packageInfo,
+                               std::string* error = nullptr,
+                               DisabledChecks disabledChecks = ENABLE_ALL_CHECKS);
+
+    /**
+     * A std::function that abstracts a list of "provided" instance names. Given package, version
+     * and interface, the function returns a list of instance names that matches.
+     * This function can represent a manifest, an IServiceManager, etc.
+     * If the source is passthrough service manager, a list of instance names cannot be provided.
+     * Instead, the function should call getService on each of the "hintInstances", and
+     * return those instances for which getService does not return a nullptr. This means that for
+     * passthrough HALs, the deprecation on <regex-instance>s cannot be enforced; only <instance>s
+     * can be enforced.
+     */
+    using ListInstances = std::function<std::vector<std::pair<std::string, Version>>(
+        const std::string& package, Version version, const std::string& interface,
+        const std::vector<std::string>& hintInstances)>;
+    /**
+     * Check deprecation on framework matrices with a provided predicate.
+     *
+     * @param listInstances predicate that takes parameter in this format:
+     *        android.hardware.foo@1.0::IFoo
+     *        and returns {{"default", version}...} if HAL is in use, where version =
+     *        first version in interfaceChain where package + major version matches.
+     *
+     * @return = 0 if success (no deprecated HALs)
+     *         > 0 if there is at least one deprecated HAL
+     *         < 0 if any error (mount partition fails, illformed XML, etc.)
+     */
+    int32_t checkDeprecation(const ListInstances& listInstances, std::string* error = nullptr);
+
+    /**
+     * Check deprecation on existing VINTF metadata. Use Device Manifest as the
+     * predicate to check if a HAL is in use.
+     *
+     * @return = 0 if success (no deprecated HALs)
+     *         > 0 if there is at least one deprecated HAL
+     *         < 0 if any error (mount partition fails, illformed XML, etc.)
+     */
+    int32_t checkDeprecation(std::string* error = nullptr);
+
+   private:
+    const std::unique_ptr<FileSystem> mFileSystem;
+    const std::unique_ptr<details::PartitionMounter> mPartitionMounter;
+    const std::unique_ptr<details::ObjectFactory<RuntimeInfo>> mRuntimeInfoFactory;
+    const std::unique_ptr<details::PropertyFetcher> mPropertyFetcher;
+
+    details::LockedSharedPtr<HalManifest> mDeviceManifest;
+    details::LockedSharedPtr<HalManifest> mFrameworkManifest;
+    details::LockedSharedPtr<CompatibilityMatrix> mDeviceMatrix;
+
+    // Parent lock of the following fields. It should be acquired before locking the child locks.
+    std::mutex mFrameworkCompatibilityMatrixMutex;
+    details::LockedSharedPtr<CompatibilityMatrix> mFrameworkMatrix;
+    details::LockedSharedPtr<CompatibilityMatrix> mCombinedFrameworkMatrix;
+    // End of mFrameworkCompatibilityMatrixMutex
+
+    details::LockedRuntimeInfoCache mDeviceRuntimeInfo;
+
+    // Expose functions for testing and recovery
+    friend class VintfObjectRecovery;
+    friend class testing::VintfObjectTestBase;
+    friend class testing::VintfObjectRuntimeInfoTest;
+    friend class testing::VintfObjectCompatibleTest;
+    int32_t checkCompatibility(const std::vector<std::string>& xmls, bool mount, std::string* error,
+                               DisabledChecks disabledChecks = ENABLE_ALL_CHECKS);
+    const std::unique_ptr<FileSystem>& getFileSystem();
+    const std::unique_ptr<details::PartitionMounter>& getPartitionMounter();
+    const std::unique_ptr<details::PropertyFetcher>& getPropertyFetcher();
+    const std::unique_ptr<details::ObjectFactory<RuntimeInfo>>& getRuntimeInfoFactory();
+
+   public:
+    /*
+     * Get global instance. By default, this fetches from root and cache results,
+     * unless skipCache is specified.
+     */
+    static std::shared_ptr<VintfObject> GetInstance();
+
+    // Static variants of member functions.
+
     /*
      * Return the API that access the device-side HAL manifest stored
      * in /vendor/manifest.xml.
@@ -112,19 +287,6 @@
                                       DisabledChecks disabledChecks = ENABLE_ALL_CHECKS);
 
     /**
-     * A std::function that abstracts a list of "provided" instance names. Given package, version
-     * and interface, the function returns a list of instance names that matches.
-     * This function can represent a manifest, an IServiceManager, etc.
-     * If the source is passthrough service manager, a list of instance names cannot be provided.
-     * Instead, the function should call getService on each of the "hintInstances", and
-     * return those instances for which getService does not return a nullptr. This means that for
-     * passthrough HALs, the deprecation on <regex-instance>s cannot be enforced; only <instance>s
-     * can be enforced.
-     */
-    using ListInstances = std::function<std::vector<std::pair<std::string, Version>>(
-        const std::string& package, Version version, const std::string& interface,
-        const std::vector<std::string>& hintInstances)>;
-    /**
      * Check deprecation on framework matrices with a provided predicate.
      *
      * @param listInstances predicate that takes parameter in this format:
@@ -149,33 +311,26 @@
      */
     static int32_t CheckDeprecation(std::string* error = nullptr);
 
-    // Specify how the file system should be queried.
-    // Can only be initialized before VintfObject is queried, preferably in main().
-    static bool InitFileSystem(std::unique_ptr<FileSystem>&&);
-
-   protected:
    private:
-    static std::unique_ptr<FileSystem> sInstance;
+    static details::LockedSharedPtr<VintfObject> sInstance;
 
-   private:
-    static status_t GetCombinedFrameworkMatrix(
-        const std::shared_ptr<const HalManifest>& deviceManifest, CompatibilityMatrix* out,
+    status_t getCombinedFrameworkMatrix(const std::shared_ptr<const HalManifest>& deviceManifest,
+                                        CompatibilityMatrix* out, std::string* error = nullptr);
+    std::vector<Named<CompatibilityMatrix>> getAllFrameworkMatrixLevels(
         std::string* error = nullptr);
-    static std::vector<Named<CompatibilityMatrix>> GetAllFrameworkMatrixLevels(
-        std::string* error = nullptr);
-    static status_t AddDirectoryManifests(const std::string& directory, HalManifest* manifests,
-                                          std::string* error = nullptr);
-    static status_t FetchDeviceHalManifest(HalManifest* out, std::string* error = nullptr);
-    static status_t FetchDeviceMatrix(CompatibilityMatrix* out, std::string* error = nullptr);
-    static status_t FetchOdmHalManifest(HalManifest* out, std::string* error = nullptr);
-    static status_t FetchOneHalManifest(const std::string& path, HalManifest* out,
-                                        std::string* error = nullptr);
-    static status_t FetchFrameworkHalManifest(HalManifest* out, std::string* error = nullptr);
+    status_t addDirectoryManifests(const std::string& directory, HalManifest* manifests,
+                                   std::string* error = nullptr);
+    status_t fetchDeviceHalManifest(HalManifest* out, std::string* error = nullptr);
+    status_t fetchDeviceMatrix(CompatibilityMatrix* out, std::string* error = nullptr);
+    status_t fetchOdmHalManifest(HalManifest* out, std::string* error = nullptr);
+    status_t fetchOneHalManifest(const std::string& path, HalManifest* out,
+                                 std::string* error = nullptr);
+    status_t fetchFrameworkHalManifest(HalManifest* out, std::string* error = nullptr);
 
-    static bool isHalDeprecated(const MatrixHal& oldMatrixHal,
+    static bool IsHalDeprecated(const MatrixHal& oldMatrixHal,
                                 const CompatibilityMatrix& targetMatrix,
                                 const ListInstances& listInstances, std::string* error);
-    static bool isInstanceDeprecated(const MatrixInstance& oldMatrixInstance,
+    static bool IsInstanceDeprecated(const MatrixInstance& oldMatrixInstance,
                                      const CompatibilityMatrix& targetMatrix,
                                      const ListInstances& listInstances, std::string* error);
 };
@@ -188,12 +343,8 @@
     DEPRECATED = 1,
 };
 
-// exposed for testing and VintfObjectRecovery.
+// exposed for testing.
 namespace details {
-class PartitionMounter;
-int32_t checkCompatibility(const std::vector<std::string>& xmls, bool mount,
-                           const PartitionMounter& partitionMounter, std::string* error,
-                           DisabledChecks disabledChecks = ENABLE_ALL_CHECKS);
 
 extern const std::string kSystemVintfDir;
 extern const std::string kVendorVintfDir;
diff --git a/test/Android.bp b/test/Android.bp
index 4dd6480..2246c12 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -66,7 +66,7 @@
     static_libs: [
         "libgtest",
         "libgmock",
-        "libvintf_common",
+        "libvintf",
         "libhidl-gen-utils",
         "libz",
     ],
diff --git a/test/utils-fake.cpp b/test/utils-fake.cpp
index a04ba79..ce82cd4 100644
--- a/test/utils-fake.cpp
+++ b/test/utils-fake.cpp
@@ -20,12 +20,6 @@
 namespace vintf {
 namespace details {
 
-// Do not create the mock objects here as InitGoogleMock must be called
-// first.
-PartitionMounter* gPartitionMounter = nullptr;
-
-ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = nullptr;
-
 MockPropertyFetcher::MockPropertyFetcher() {
     using namespace ::testing;
     using namespace std::placeholders;
@@ -33,11 +27,6 @@
         .WillByDefault(Invoke(std::bind(&PropertyFetcher::getProperty, real_, _1, _2)));
 }
 
-MockPropertyFetcher* gPropertyFetcher = nullptr;
-const PropertyFetcher& getPropertyFetcher() {
-    return *gPropertyFetcher;
-}
-
 }  // namespace details
 }  // namespace vintf
 }  // namespace android
diff --git a/test/utils-fake.h b/test/utils-fake.h
index f07ae48..653c3b9 100644
--- a/test/utils-fake.h
+++ b/test/utils-fake.h
@@ -108,11 +108,12 @@
    public:
     MockPropertyFetcher();
     MOCK_CONST_METHOD2(getProperty, std::string(const std::string&, const std::string&));
+    MOCK_CONST_METHOD2(getBoolProperty, bool(const std::string&, bool));
+    MOCK_CONST_METHOD3(getUintProperty, uint64_t(const std::string&, uint64_t, uint64_t));
 
    private:
-    PropertyFetcher real_;
+    PropertyFetcherImpl real_;
 };
-extern MockPropertyFetcher* gPropertyFetcher;
 
 }  // namespace details
 }  // namespace vintf
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index 250861f..34cee2d 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -29,8 +29,6 @@
 #include <hidl-util/FQName.h>
 
 using namespace ::testing;
-using namespace ::android::vintf;
-using namespace ::android::vintf::details;
 
 using android::FqInstance;
 
@@ -41,6 +39,12 @@
 #define EXPECT_IN(sub, str) EXPECT_TRUE(In((sub), (str)))
 #define EXPECT_NOT_IN(sub, str) EXPECT_FALSE(In((sub), (str)))
 
+namespace android {
+namespace vintf {
+namespace testing {
+
+using namespace ::android::vintf::details;
+
 //
 // Set of Xml1 metadata compatible with each other.
 //
@@ -277,76 +281,90 @@
     "    </hal>\n"
     "</compatibility-matrix>\n"};
 
-static MockPartitionMounter& mounter() {
-    return *static_cast<MockPartitionMounter*>(gPartitionMounter);
-}
-static MockFileSystem& fetcher() {
-    return static_cast<MockFileSystem&>(details::getFileSystem());
-}
-
-// Setup the MockFileSystem used by the fetchAllInformation template
-// so it returns the given metadata info instead of fetching from device.
-void setupMockFetcher(const std::string& vendorManifestXml, const std::string& systemMatrixXml,
-                      const std::string& systemManifestXml, const std::string& vendorMatrixXml,
-                      const std::string& productModel) {
-    ON_CALL(fetcher(), listFiles(StrEq(kVendorManifestFragmentDir), _, _))
-        .WillByDefault(Return(::android::OK));
-    ON_CALL(fetcher(), listFiles(StrEq(kSystemManifestFragmentDir), _, _))
-        .WillByDefault(Return(::android::OK));
-    ON_CALL(fetcher(), listFiles(StrEq(kOdmManifestFragmentDir), _, _))
-        .WillByDefault(Return(::android::OK));
-
-    if (!productModel.empty()) {
-        ON_CALL(fetcher(),
-                fetch(StrEq(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml"), _))
-            .WillByDefault(Return(::android::NAME_NOT_FOUND));
-        ON_CALL(fetcher(), fetch(StrEq(kOdmVintfDir + "manifest_" + productModel + ".xml"), _))
-            .WillByDefault(Return(::android::NAME_NOT_FOUND));
-    }
-    ON_CALL(fetcher(), fetch(StrEq(kOdmLegacyManifest), _))
-        .WillByDefault(Return(::android::NAME_NOT_FOUND));
-    ON_CALL(fetcher(), fetch(StrEq(kOdmManifest), _))
-        .WillByDefault(Return(::android::NAME_NOT_FOUND));
-    ON_CALL(fetcher(), fetch(StrEq(kVendorManifest), _))
-        .WillByDefault(Return(::android::NAME_NOT_FOUND));
-    ON_CALL(fetcher(), fetch(StrEq(kVendorLegacyManifest), _))
-        .WillByDefault(Invoke([vendorManifestXml](const std::string& path, std::string& fetched) {
-            (void)path;
-            fetched = vendorManifestXml;
-            return 0;
-        }));
-    ON_CALL(fetcher(), fetch(StrEq(kSystemManifest), _))
-        .WillByDefault(Invoke([systemManifestXml](const std::string& path, std::string& fetched) {
-            (void)path;
-            fetched = systemManifestXml;
-            return 0;
-        }));
-    ON_CALL(fetcher(), fetch(StrEq(kVendorMatrix), _))
-        .WillByDefault(Return(::android::NAME_NOT_FOUND));
-    ON_CALL(fetcher(), fetch(StrEq(kVendorLegacyMatrix), _))
-        .WillByDefault(Invoke([vendorMatrixXml](const std::string& path, std::string& fetched) {
-            (void)path;
-            fetched = vendorMatrixXml;
-            return 0;
-        }));
-    ON_CALL(fetcher(), fetch(StrEq(kSystemLegacyMatrix), _))
-        .WillByDefault(Invoke([systemMatrixXml](const std::string& path, std::string& fetched) {
-            (void)path;
-            fetched = systemMatrixXml;
-            return 0;
-        }));
-    // Don't list /system/etc/vintf unless otherwise specified.
-    ON_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
-        .WillByDefault(Return(::android::OK));
-}
-
-class VintfObjectTestBase : public testing::Test {
+class VintfObjectTestBase : public ::testing::Test {
    protected:
-    virtual void SetUp() {
+    MockPartitionMounter& mounter() {
+        return static_cast<MockPartitionMounter&>(*vintfObject->getPartitionMounter());
+    }
+    MockFileSystem& fetcher() {
+        return static_cast<MockFileSystem&>(*vintfObject->getFileSystem());
+    }
+    MockPropertyFetcher& propertyFetcher() {
+        return static_cast<MockPropertyFetcher&>(*vintfObject->getPropertyFetcher());
+    }
+
+    // Setup the MockFileSystem used by the fetchAllInformation template
+    // so it returns the given metadata info instead of fetching from device.
+    void setupMockFetcher(const std::string& vendorManifestXml, const std::string& systemMatrixXml,
+                          const std::string& systemManifestXml, const std::string& vendorMatrixXml,
+                          const std::string& productModel) {
+        ON_CALL(fetcher(), listFiles(StrEq(kVendorManifestFragmentDir), _, _))
+            .WillByDefault(Return(::android::OK));
+        ON_CALL(fetcher(), listFiles(StrEq(kSystemManifestFragmentDir), _, _))
+            .WillByDefault(Return(::android::OK));
+        ON_CALL(fetcher(), listFiles(StrEq(kOdmManifestFragmentDir), _, _))
+            .WillByDefault(Return(::android::OK));
+
+        if (!productModel.empty()) {
+            ON_CALL(fetcher(),
+                    fetch(StrEq(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml"), _))
+                .WillByDefault(Return(::android::NAME_NOT_FOUND));
+            ON_CALL(fetcher(), fetch(StrEq(kOdmVintfDir + "manifest_" + productModel + ".xml"), _))
+                .WillByDefault(Return(::android::NAME_NOT_FOUND));
+        }
+        ON_CALL(fetcher(), fetch(StrEq(kOdmLegacyManifest), _))
+            .WillByDefault(Return(::android::NAME_NOT_FOUND));
+        ON_CALL(fetcher(), fetch(StrEq(kOdmManifest), _))
+            .WillByDefault(Return(::android::NAME_NOT_FOUND));
+        ON_CALL(fetcher(), fetch(StrEq(kVendorManifest), _))
+            .WillByDefault(Return(::android::NAME_NOT_FOUND));
+        ON_CALL(fetcher(), fetch(StrEq(kVendorLegacyManifest), _))
+            .WillByDefault(
+                Invoke([vendorManifestXml](const std::string& path, std::string& fetched) {
+                    (void)path;
+                    fetched = vendorManifestXml;
+                    return 0;
+                }));
+        ON_CALL(fetcher(), fetch(StrEq(kSystemManifest), _))
+            .WillByDefault(
+                Invoke([systemManifestXml](const std::string& path, std::string& fetched) {
+                    (void)path;
+                    fetched = systemManifestXml;
+                    return 0;
+                }));
+        ON_CALL(fetcher(), fetch(StrEq(kVendorMatrix), _))
+            .WillByDefault(Return(::android::NAME_NOT_FOUND));
+        ON_CALL(fetcher(), fetch(StrEq(kVendorLegacyMatrix), _))
+            .WillByDefault(Invoke([vendorMatrixXml](const std::string& path, std::string& fetched) {
+                (void)path;
+                fetched = vendorMatrixXml;
+                return 0;
+            }));
+        ON_CALL(fetcher(), fetch(StrEq(kSystemLegacyMatrix), _))
+            .WillByDefault(Invoke([systemMatrixXml](const std::string& path, std::string& fetched) {
+                (void)path;
+                fetched = systemMatrixXml;
+                return 0;
+            }));
+        // Don't list /system/etc/vintf unless otherwise specified.
+        ON_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
+            .WillByDefault(Return(::android::OK));
+    }
+
+    void setFakeProperties() {
         productModel = "fake_sku";
-        ON_CALL(*gPropertyFetcher, getProperty("ro.boot.product.hardware.sku", _))
+        ON_CALL(propertyFetcher(), getProperty("ro.boot.product.hardware.sku", _))
             .WillByDefault(Return(productModel));
     }
+
+    virtual void SetUp() {
+        vintfObject =
+            std::make_unique<VintfObject>(std::make_unique<NiceMock<MockFileSystem>>(),
+                                          std::make_unique<NiceMock<MockPartitionMounter>>(),
+                                          std::make_unique<NiceMock<MockRuntimeInfoFactory>>(
+                                              std::make_shared<NiceMock<MockRuntimeInfo>>()),
+                                          std::make_unique<NiceMock<MockPropertyFetcher>>());
+    }
     virtual void TearDown() {
         Mock::VerifyAndClear(&mounter());
         Mock::VerifyAndClear(&fetcher());
@@ -413,6 +431,7 @@
     }
 
     std::string productModel;
+    std::unique_ptr<VintfObject> vintfObject;
 };
 
 // Test fixture that provides compatible metadata from the mock device.
@@ -420,10 +439,16 @@
    protected:
     virtual void SetUp() {
         VintfObjectTestBase::SetUp();
+        setFakeProperties();
         mounter().reset();
         setupMockFetcher(vendorManifestXml1, systemMatrixXml1, systemManifestXml1, vendorMatrixXml1,
                          productModel);
     }
+
+    // Access to private method for force mounting.
+    int checkCompatibility(const std::vector<std::string>& xmls, bool mount, std::string* error) {
+        return vintfObject->checkCompatibility(xmls, mount, error);
+    }
 };
 
 // Tests that local info is checked.
@@ -440,7 +465,7 @@
     EXPECT_CALL(mounter(), mountVendor()).Times(0);
     EXPECT_CALL(mounter(), umountVendor()).Times(0);
 
-    int result = VintfObject::CheckCompatibility(packageInfo, &error);
+    int result = vintfObject->checkCompatibility(packageInfo, &error);
 
     ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
     // Check that nothing was ignored.
@@ -458,7 +483,7 @@
     EXPECT_CALL(mounter(), mountVendor()).Times(2);
     EXPECT_CALL(mounter(), umountVendor()).Times(1);
 
-    int result = details::checkCompatibility(packageInfo, true /* mount */, mounter(), &error);
+    int result = checkCompatibility(packageInfo, true /* mount */, &error);
 
     ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
     EXPECT_FALSE(mounter().systemMounted());
@@ -479,7 +504,7 @@
     EXPECT_CALL(mounter(), mountVendor()).Times(0);
     EXPECT_CALL(mounter(), umountVendor()).Times(0);
 
-    int result = VintfObject::CheckCompatibility(packageInfo, &error);
+    int result = vintfObject->checkCompatibility(packageInfo, &error);
 
     ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
     ASSERT_STREQ(error.c_str(), "");
@@ -496,7 +521,7 @@
     EXPECT_CALL(mounter(), mountVendor()).Times(2);
     EXPECT_CALL(mounter(), umountVendor()).Times(1);
 
-    int result = details::checkCompatibility(packageInfo, true /* mount */, mounter(), &error);
+    int result = checkCompatibility(packageInfo, true /* mount */, &error);
 
     ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
     EXPECT_FALSE(mounter().systemMounted());
@@ -508,7 +533,7 @@
     std::string error;
     std::vector<std::string> packageInfo = {systemMatrixXml2};
 
-    int result = VintfObject::CheckCompatibility(packageInfo, &error);
+    int result = vintfObject->checkCompatibility(packageInfo, &error);
 
     ASSERT_EQ(result, 1) << "Should have failed:" << error.c_str();
     EXPECT_IN(
@@ -523,7 +548,7 @@
     std::string error;
     std::vector<std::string> packageInfo = {systemMatrixXml2, vendorManifestXml2};
 
-    int result = VintfObject::CheckCompatibility(packageInfo, &error);
+    int result = vintfObject->checkCompatibility(packageInfo, &error);
 
     ASSERT_EQ(result, 0) << "Failed message:" << error.c_str();
     ASSERT_STREQ(error.c_str(), "");
@@ -542,7 +567,7 @@
     EXPECT_CALL(mounter(), mountVendor()).Times(0);
     EXPECT_CALL(mounter(), umountVendor()).Times(0);
 
-    int result = VintfObject::CheckCompatibility(packageInfo, &error);
+    int result = vintfObject->checkCompatibility(packageInfo, &error);
 
     ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
     ASSERT_STREQ(error.c_str(), "");
@@ -559,7 +584,7 @@
     EXPECT_CALL(mounter(), mountVendor()).Times(2);
     EXPECT_CALL(mounter(), umountVendor()).Times(1);
 
-    int result = details::checkCompatibility(packageInfo, true /* mount */, mounter(), &error);
+    int result = checkCompatibility(packageInfo, true /* mount */, &error);
 
     ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
     EXPECT_FALSE(mounter().systemMounted());
@@ -580,7 +605,7 @@
     EXPECT_CALL(mounter(), mountVendor()).Times(0);
     EXPECT_CALL(mounter(), umountVendor()).Times(0);
 
-    int result = VintfObject::CheckCompatibility(packageInfo, &error);
+    int result = vintfObject->checkCompatibility(packageInfo, &error);
 
     ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
     ASSERT_STREQ(error.c_str(), "");
@@ -598,7 +623,7 @@
     EXPECT_CALL(mounter(), mountVendor()).Times(0);
     EXPECT_CALL(mounter(), umountVendor()).Times(1);
 
-    int result = details::checkCompatibility(packageInfo, true /* mount */, mounter(), &error);
+    int result = checkCompatibility(packageInfo, true /* mount */, &error);
 
     ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
     EXPECT_FALSE(mounter().systemMounted());
@@ -610,6 +635,7 @@
    protected:
     virtual void SetUp() {
         VintfObjectTestBase::SetUp();
+        setFakeProperties();
         mounter().reset();
         setupMockFetcher(vendorManifestXml1, systemMatrixXml2, systemManifestXml1, vendorMatrixXml1,
                          productModel);
@@ -626,7 +652,7 @@
     expectVendorMatrix();
     expectSystemMatrix();
 
-    int result = VintfObject::CheckCompatibility(packageInfo, &error);
+    int result = vintfObject->checkCompatibility(packageInfo, &error);
 
     ASSERT_EQ(result, 1) << "Should have failed:" << error.c_str();
 }
@@ -641,28 +667,28 @@
     expectVendorMatrix();
     expectSystemMatrix(0);
 
-    int result = VintfObject::CheckCompatibility(packageInfo, &error);
+    int result = vintfObject->checkCompatibility(packageInfo, &error);
 
     ASSERT_EQ(result, 0) << "Failed message:" << error.c_str();
     ASSERT_STREQ(error.c_str(), "");
 }
 
-static MockRuntimeInfoFactory& runtimeInfoFactory() {
-    return *static_cast<MockRuntimeInfoFactory*>(gRuntimeInfoFactory);
-}
-
 // Test fixture that provides compatible metadata from the mock device.
-class VintfObjectRuntimeInfoTest : public testing::Test {
+class VintfObjectRuntimeInfoTest : public VintfObjectTestBase {
    protected:
     virtual void SetUp() {
+        VintfObjectTestBase::SetUp();
         // clear fetch flags
         runtimeInfoFactory().getInfo()->failNextFetch();
-        VintfObject::GetRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::ALL);
+        vintfObject->getRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::ALL);
     }
     virtual void TearDown() {
         Mock::VerifyAndClear(&runtimeInfoFactory());
         Mock::VerifyAndClear(runtimeInfoFactory().getInfo().get());
     }
+    MockRuntimeInfoFactory& runtimeInfoFactory() {
+        return static_cast<MockRuntimeInfoFactory&>(*vintfObject->getRuntimeInfoFactory());
+    }
 };
 
 TEST_F(VintfObjectRuntimeInfoTest, GetRuntimeInfo) {
@@ -679,18 +705,28 @@
     EXPECT_CALL(*runtimeInfoFactory().getInfo(), fetchAllInformation(RuntimeInfo::FetchFlag::ALL));
     EXPECT_CALL(*runtimeInfoFactory().getInfo(), fetchAllInformation(RuntimeInfo::FetchFlag::NONE));
 
-    VintfObject::GetRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
-    VintfObject::GetRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
-    VintfObject::GetRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
-    VintfObject::GetRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::ALL);
-    VintfObject::GetRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::ALL);
-    VintfObject::GetRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::ALL);
+    vintfObject->getRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
+    vintfObject->getRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
+    vintfObject->getRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
+    vintfObject->getRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::ALL);
+    vintfObject->getRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::ALL);
+    vintfObject->getRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::ALL);
 }
 
 // Test fixture that provides incompatible metadata from the mock device.
 class VintfObjectTest : public VintfObjectTestBase {
    protected:
-    virtual void SetUp() {}
+    virtual void SetUp() {
+        VintfObjectTestBase::SetUp();
+
+        // By default use empty filesystem
+        EXPECT_CALL(fetcher(), listFiles(_, _, _))
+            .Times(AnyNumber())
+            .WillRepeatedly(Return(::android::OK));
+        EXPECT_CALL(fetcher(), fetch(_, _))
+            .Times(AnyNumber())
+            .WillRepeatedly(Return(::android::NAME_NOT_FOUND));
+    }
 };
 
 // Test framework compatibility matrix is combined at runtime
@@ -707,9 +743,10 @@
                 "<compatibility-matrix version=\"1.0\" type=\"framework\" level=\"1\"/>");
     expectFetch(kSystemVintfDir + "compatibility_matrix.empty.xml",
                 "<compatibility-matrix version=\"1.0\" type=\"framework\"/>");
+    expectFetch(kVendorManifest, "<manifest version=\"1.0\" type=\"device\" />\n");
     expectSystemMatrix(0);
 
-    EXPECT_NE(nullptr, VintfObject::GetFrameworkCompatibilityMatrix(true /* skipCache */));
+    EXPECT_NE(nullptr, vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */));
 }
 
 const std::string vendorEtcManifest =
@@ -801,7 +838,7 @@
     }
     void noOdmManifest() { expectFileNotExist(StartsWith("/odm/")); }
     std::shared_ptr<const HalManifest> get() {
-        return VintfObject::GetDeviceHalManifest(true /* skipCache */);
+        return vintfObject->getDeviceHalManifest(true /* skipCache */);
     }
 };
 
@@ -857,6 +894,7 @@
 class OdmManifestTest : public VintfObjectTestBase {
    protected:
     virtual void SetUp() override {
+        VintfObjectTestBase::SetUp();
         // Assume /vendor/etc/vintf/manifest.xml does not exist to simplify
         // testing logic.
         expectFileNotExist(StrEq(kVendorManifest));
@@ -866,7 +904,7 @@
         expectFileNotExist(StartsWith("/odm/"));
     }
     std::shared_ptr<const HalManifest> get() {
-        return VintfObject::GetDeviceHalManifest(true /* skipCache */);
+        return vintfObject->getDeviceHalManifest(true /* skipCache */);
     }
 };
 
@@ -930,6 +968,7 @@
 class DeprecateTest : public VintfObjectTestBase {
    protected:
     virtual void SetUp() override {
+        VintfObjectTestBase::SetUp();
         EXPECT_CALL(fetcher(), listFiles(StrEq(kSystemVintfDir), _, _))
             .WillRepeatedly(Invoke([](const auto&, auto* out, auto*) {
                 *out = {
@@ -952,7 +991,7 @@
 
         // Update the device manifest cache because CheckDeprecate does not fetch
         // device manifest again if cache exist.
-        VintfObject::GetDeviceHalManifest(true /* skipCache */);
+        vintfObject->getDeviceHalManifest(true /* skipCache */);
     }
 
 };
@@ -963,7 +1002,7 @@
         "android.hardware.major@2.0::IMajor/default",
     });
     std::string error;
-    EXPECT_EQ(NO_DEPRECATED_HALS, VintfObject::CheckDeprecation(pred, &error)) << error;
+    EXPECT_EQ(NO_DEPRECATED_HALS, vintfObject->checkDeprecation(pred, &error)) << error;
 }
 
 TEST_F(DeprecateTest, CheckRemoved) {
@@ -973,7 +1012,7 @@
         "android.hardware.major@2.0::IMajor/default",
     });
     std::string error;
-    EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error))
+    EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
         << "removed@1.0 should be deprecated. " << error;
 }
 
@@ -983,7 +1022,7 @@
         "android.hardware.major@2.0::IMajor/default",
     });
     std::string error;
-    EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error))
+    EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
         << "minor@1.0 should be deprecated. " << error;
 }
 
@@ -994,7 +1033,7 @@
         "android.hardware.major@2.0::IMajor/default",
     });
     std::string error;
-    EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error))
+    EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
         << "minor@1.0::IMinor/legacy should be deprecated. " << error;
 }
 
@@ -1005,7 +1044,7 @@
         "android.hardware.major@2.0::IMajor/default",
     });
     std::string error;
-    EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error))
+    EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
         << "minor@1.1::IMinor/legacy should be deprecated. " << error;
 }
 
@@ -1016,7 +1055,7 @@
         "android.hardware.major@2.0::IMajor/default",
     });
     std::string error;
-    EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error))
+    EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
         << "major@1.0 should be deprecated. " << error;
 }
 
@@ -1026,7 +1065,7 @@
         "android.hardware.major@1.0::IMajor/default",
     });
     std::string error;
-    EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error))
+    EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
         << "major@1.0 should be deprecated. " << error;
 }
 
@@ -1061,18 +1100,21 @@
     void expectTargetFcmVersion(size_t level) {
         expectFetch(kVendorManifest, "<manifest version=\"1.0\" type=\"device\" target-level=\"" +
                                          to_string(static_cast<Level>(level)) + "\"/>");
-        VintfObject::GetDeviceHalManifest(true /* skipCache */);
+        vintfObject->getDeviceHalManifest(true /* skipCache */);
     }
 };
 
 class RegexTest : public MultiMatrixTest {
    protected:
-    virtual void SetUp() { SetUpMockSystemMatrices(systemMatrixRegexXmls); }
+    virtual void SetUp() {
+        MultiMatrixTest::SetUp();
+        SetUpMockSystemMatrices(systemMatrixRegexXmls);
+    }
 };
 
 TEST_F(RegexTest, CombineLevel1) {
     expectTargetFcmVersion(1);
-    auto matrix = VintfObject::GetFrameworkCompatibilityMatrix(true /* skipCache */);
+    auto matrix = vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */);
     ASSERT_NE(nullptr, matrix);
     std::string xml = gCompatibilityMatrixConverter(*matrix);
 
@@ -1127,7 +1169,7 @@
 
 TEST_F(RegexTest, CombineLevel2) {
     expectTargetFcmVersion(2);
-    auto matrix = VintfObject::GetFrameworkCompatibilityMatrix(true /* skipCache */);
+    auto matrix = vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */);
     ASSERT_NE(nullptr, matrix);
     std::string xml = gCompatibilityMatrixConverter(*matrix);
 
@@ -1179,7 +1221,7 @@
         "android.hardware.regex@1.1::IRegex/regex_common/0",
         "android.hardware.regex@2.0::IRegex/default",
     });
-    EXPECT_EQ(NO_DEPRECATED_HALS, VintfObject::CheckDeprecation(pred, &error)) << error;
+    EXPECT_EQ(NO_DEPRECATED_HALS, vintfObject->checkDeprecation(pred, &error)) << error;
 
     for (const auto& deprecated : {
              "android.hardware.regex@1.0::IRegex/default",
@@ -1195,7 +1237,7 @@
             "android.hardware.regex@2.0::IRegex/default",
         });
         error.clear();
-        EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error))
+        EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
             << deprecated << " should be deprecated. " << error;
     }
 }
@@ -1209,7 +1251,7 @@
         "android.hardware.regex@2.0::IRegex/regex/2.0/1",
         "android.hardware.regex@2.0::IRegex/default",
     });
-    EXPECT_EQ(NO_DEPRECATED_HALS, VintfObject::CheckDeprecation(pred, &error)) << error;
+    EXPECT_EQ(NO_DEPRECATED_HALS, vintfObject->checkDeprecation(pred, &error)) << error;
 
     for (const auto& deprecated : {
              "android.hardware.regex@1.0::IRegex/default",
@@ -1229,7 +1271,7 @@
         });
 
         error.clear();
-        EXPECT_EQ(DEPRECATED, VintfObject::CheckDeprecation(pred, &error))
+        EXPECT_EQ(DEPRECATED, vintfObject->checkDeprecation(pred, &error))
             << deprecated << " should be deprecated.";
     }
 }
@@ -1273,7 +1315,7 @@
     SetUpMockSystemMatrices({systemMatrixKernelXmls[0], systemMatrixKernelXmls[1]});
 
     expectTargetFcmVersion(1);
-    auto matrix = VintfObject::GetFrameworkCompatibilityMatrix(true /* skipCache */);
+    auto matrix = vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */);
     ASSERT_NE(nullptr, matrix);
     std::string xml = gCompatibilityMatrixConverter(*matrix);
 
@@ -1291,7 +1333,7 @@
     SetUpMockSystemMatrices({systemMatrixKernelXmls});
 
     expectTargetFcmVersion(1);
-    auto matrix = VintfObject::GetFrameworkCompatibilityMatrix(true /* skipCache */);
+    auto matrix = vintfObject->getFrameworkCompatibilityMatrix(true /* skipCache */);
     ASSERT_NE(nullptr, matrix);
     std::string xml = gCompatibilityMatrixConverter(*matrix);
 
@@ -1305,23 +1347,11 @@
     EXPECT_NOT_IN(FAKE_KERNEL("4.0.0", "D3"), xml) << "\nOld requirements must not change";
 }
 
+}  // namespace testing
+}  // namespace vintf
+}  // namespace android
+
 int main(int argc, char** argv) {
     ::testing::InitGoogleMock(&argc, argv);
-
-    if (!VintfObject::InitFileSystem(std::make_unique<NiceMock<MockFileSystem>>())) {
-        LOG(FATAL) << "Cannot set mock file system because it is already initialized.";
-        return 1;
-    }
-
-    NiceMock<MockPartitionMounter> mounter;
-    gPartitionMounter = &mounter;
-
-    NiceMock<MockRuntimeInfoFactory> runtimeInfoFactory(
-        std::make_shared<NiceMock<MockRuntimeInfo>>());
-    gRuntimeInfoFactory = &runtimeInfoFactory;
-
-    NiceMock<MockPropertyFetcher> properties;
-    gPropertyFetcher = &properties;
-
     return RUN_ALL_TESTS();
 }
diff --git a/utils.cpp b/utils.cpp
deleted file mode 100644
index c6425d8..0000000
--- a/utils.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "utils.h"
-
-#ifdef LIBVINTF_TARGET
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#endif
-
-namespace android {
-namespace vintf {
-namespace details {
-
-static PartitionMounter partitionMounter;
-PartitionMounter* gPartitionMounter = &partitionMounter;
-
-static ObjectFactory<RuntimeInfo> runtimeInfoFactory;
-ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = &runtimeInfoFactory;
-
-#ifdef LIBVINTF_TARGET
-class DevicePropertyFetcher : public PropertyFetcher {
-   public:
-    std::string getProperty(const std::string& key,
-                            const std::string& defaultValue) const override {
-        return android::base::GetProperty(key, defaultValue);
-    }
-    uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
-                             uint64_t max) const override {
-        return android::base::GetUintProperty(key, defaultValue, max);
-    }
-    bool getBoolProperty(const std::string& key, bool defaultValue) const override {
-        return android::base::GetBoolProperty(key, defaultValue);
-    }
-};
-const PropertyFetcher& getPropertyFetcher() {
-    static DevicePropertyFetcher fetcher;
-    return fetcher;
-}
-#else
-const PropertyFetcher& getPropertyFetcher() {
-    static PropertyFetcher fetcher;
-    return fetcher;
-}
-#endif
-
-}  // namespace details
-}  // namespace vintf
-}  // namespace android
diff --git a/utils.h b/utils.h
index e33d283..8ccda3e 100644
--- a/utils.h
+++ b/utils.h
@@ -38,14 +38,11 @@
     virtual status_t umountVendor() const { return OK; }
 };
 
-extern PartitionMounter* gPartitionMounter;
-
 template <typename T>
-status_t fetchAllInformation(const std::string& path, const XmlConverter<T>& converter,
-                             T* outObject, std::string* error = nullptr) {
+status_t fetchAllInformation(const FileSystem* fileSystem, const std::string& path,
+                             const XmlConverter<T>& converter, T* outObject, std::string* error) {
     std::string info;
-
-    status_t result = getFileSystem().fetch(path, &info, error);
+    status_t result = fileSystem->fetch(path, &info, error);
 
     if (result != OK) {
         return result;
@@ -67,7 +64,6 @@
     virtual ~ObjectFactory() = default;
     virtual std::shared_ptr<T> make_shared() const { return std::make_shared<T>(); }
 };
-extern ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory;
 
 // TODO(b/70628538): Do not infer from Shipping API level.
 inline Level convertFromApiLevel(size_t apiLevel) {
@@ -86,13 +82,29 @@
    public:
     virtual ~PropertyFetcher() = default;
     virtual std::string getProperty(const std::string& key,
+                                    const std::string& defaultValue = "") const = 0;
+    virtual uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
+                                     uint64_t max = UINT64_MAX) const = 0;
+    virtual bool getBoolProperty(const std::string& key, bool defaultValue) const = 0;
+};
+
+class PropertyFetcherImpl : public PropertyFetcher {
+   public:
+    virtual std::string getProperty(const std::string& key,
                                     const std::string& defaultValue = "") const;
     virtual uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
                                      uint64_t max = UINT64_MAX) const;
     virtual bool getBoolProperty(const std::string& key, bool defaultValue) const;
 };
 
-const PropertyFetcher& getPropertyFetcher();
+class PropertyFetcherNoOp : public PropertyFetcher {
+   public:
+    virtual std::string getProperty(const std::string& key,
+                                    const std::string& defaultValue = "") const override;
+    virtual uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
+                                     uint64_t max = UINT64_MAX) const override;
+    virtual bool getBoolProperty(const std::string& key, bool defaultValue) const override;
+};
 
 }  // namespace details
 }  // namespace vintf