Fix ownership of objects returned by VintfObject::Get*

VintfObject::Get* is not thread-safe; the raw pointers
returned to clients can be invalidated by another thread
that calls the same VintfObject::Get* with skipCache = true.

Fix this by sharing ownership to callers as well.
VintfObject::Get* now returns a shared_ptr, and clients
can destroy the shared_ptr once they finish reading it.

Test: libvintf_test
Test: vintf_object_test
Test: `adb shell vintf` shows compatible

Bug: 65166415

Change-Id: I931cf0864a8dba3d83fe41f715b94e1a21b266eb
diff --git a/VintfObject.cpp b/VintfObject.cpp
index f785e6b..0f590b6 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -28,20 +28,14 @@
 namespace vintf {
 
 template <typename T>
-struct LockedUniquePtr {
-    std::unique_ptr<T> object;
+struct LockedSharedPtr {
+    std::shared_ptr<T> object;
     std::mutex mutex;
 };
 
-static LockedUniquePtr<HalManifest> gDeviceManifest;
-static LockedUniquePtr<HalManifest> gFrameworkManifest;
-static LockedUniquePtr<CompatibilityMatrix> gDeviceMatrix;
-static LockedUniquePtr<CompatibilityMatrix> gFrameworkMatrix;
-static LockedUniquePtr<RuntimeInfo> gDeviceRuntimeInfo;
-
 template <typename T, typename F>
-static const T *Get(
-        LockedUniquePtr<T> *ptr,
+static std::shared_ptr<const T> Get(
+        LockedSharedPtr<T> *ptr,
         bool skipCache,
         const F &fetchAllInformation) {
     std::unique_lock<std::mutex> _lock(ptr->mutex);
@@ -51,18 +45,20 @@
             ptr->object = nullptr; // frees the old object
         }
     }
-    return ptr->object.get();
+    return ptr->object;
 }
 
 // static
-const HalManifest *VintfObject::GetDeviceHalManifest(bool skipCache) {
+std::shared_ptr<const HalManifest> VintfObject::GetDeviceHalManifest(bool skipCache) {
+    static LockedSharedPtr<HalManifest> gDeviceManifest;
     return Get(&gDeviceManifest, skipCache,
             std::bind(&HalManifest::fetchAllInformation, std::placeholders::_1,
                 "/vendor/manifest.xml"));
 }
 
 // static
-const HalManifest *VintfObject::GetFrameworkHalManifest(bool skipCache) {
+std::shared_ptr<const HalManifest> VintfObject::GetFrameworkHalManifest(bool skipCache) {
+    static LockedSharedPtr<HalManifest> gFrameworkManifest;
     return Get(&gFrameworkManifest, skipCache,
             std::bind(&HalManifest::fetchAllInformation, std::placeholders::_1,
                 "/system/manifest.xml"));
@@ -70,21 +66,24 @@
 
 
 // static
-const CompatibilityMatrix *VintfObject::GetDeviceCompatibilityMatrix(bool skipCache) {
+std::shared_ptr<const CompatibilityMatrix> VintfObject::GetDeviceCompatibilityMatrix(bool skipCache) {
+    static LockedSharedPtr<CompatibilityMatrix> gDeviceMatrix;
     return Get(&gDeviceMatrix, skipCache,
             std::bind(&CompatibilityMatrix::fetchAllInformation, std::placeholders::_1,
                 "/vendor/compatibility_matrix.xml"));
 }
 
 // static
-const CompatibilityMatrix *VintfObject::GetFrameworkCompatibilityMatrix(bool skipCache) {
+std::shared_ptr<const CompatibilityMatrix> VintfObject::GetFrameworkCompatibilityMatrix(bool skipCache) {
+    static LockedSharedPtr<CompatibilityMatrix> gFrameworkMatrix;
     return Get(&gFrameworkMatrix, skipCache,
             std::bind(&CompatibilityMatrix::fetchAllInformation, std::placeholders::_1,
                 "/system/compatibility_matrix.xml"));
 }
 
 // static
-const RuntimeInfo *VintfObject::GetRuntimeInfo(bool skipCache) {
+std::shared_ptr<const RuntimeInfo> VintfObject::GetRuntimeInfo(bool skipCache) {
+    static LockedSharedPtr<RuntimeInfo> gDeviceRuntimeInfo;
     return Get(&gDeviceRuntimeInfo, skipCache,
             std::bind(&RuntimeInfo::fetchAllInformation, std::placeholders::_1));
 }
@@ -110,8 +109,8 @@
 
 template<typename T>
 static ParseStatus tryParse(const std::string &xml, const XmlConverter<T> &parse,
-        std::unique_ptr<T> *fwk, std::unique_ptr<T> *dev) {
-    std::unique_ptr<T> ret = std::make_unique<T>();
+        std::shared_ptr<T> *fwk, std::shared_ptr<T> *dev) {
+    std::shared_ptr<T> ret = std::make_shared<T>();
     if (!parse(ret.get(), xml)) {
         return ParseStatus::PARSE_ERROR;
     }
@@ -130,9 +129,9 @@
 }
 
 template<typename T, typename GetFunction>
-static status_t getMissing(const T *pkg, bool mount,
+static status_t getMissing(const std::shared_ptr<T>& pkg, bool mount,
         std::function<status_t(void)> mountFunction,
-        const T **updated,
+        std::shared_ptr<const T>* updated,
         GetFunction getFunction) {
     if (pkg != nullptr) {
         *updated = pkg;
@@ -152,8 +151,8 @@
 
 struct PackageInfo {
     struct Pair {
-        std::unique_ptr<HalManifest>         manifest;
-        std::unique_ptr<CompatibilityMatrix> matrix;
+        std::shared_ptr<HalManifest>         manifest;
+        std::shared_ptr<CompatibilityMatrix> matrix;
     };
     Pair dev;
     Pair fwk;
@@ -161,12 +160,12 @@
 
 struct UpdatedInfo {
     struct Pair {
-        const HalManifest         *manifest;
-        const CompatibilityMatrix *matrix;
+        std::shared_ptr<const HalManifest>         manifest;
+        std::shared_ptr<const CompatibilityMatrix> matrix;
     };
     Pair dev;
     Pair fwk;
-    const RuntimeInfo *runtimeInfo;
+    std::shared_ptr<const RuntimeInfo> runtimeInfo;
 };
 
 // Checks given compatibility info against info on the device. If no
@@ -207,23 +206,23 @@
     auto mountSystem = [&mounter] { return mounter.mountSystem(); };
     auto mountVendor = [&mounter] { return mounter.mountVendor(); };
     if ((status = getMissing(
-             pkg.fwk.manifest.get(), mount, mountSystem, &updated.fwk.manifest,
+             pkg.fwk.manifest, mount, mountSystem, &updated.fwk.manifest,
              std::bind(VintfObject::GetFrameworkHalManifest, true /* skipCache */))) != OK) {
         return status;
     }
     if ((status = getMissing(
-             pkg.dev.manifest.get(), mount, mountVendor, &updated.dev.manifest,
+             pkg.dev.manifest, mount, mountVendor, &updated.dev.manifest,
              std::bind(VintfObject::GetDeviceHalManifest, true /* skipCache */))) != OK) {
         return status;
     }
     if ((status = getMissing(
-             pkg.fwk.matrix.get(), mount, mountSystem, &updated.fwk.matrix,
+             pkg.fwk.matrix, mount, mountSystem, &updated.fwk.matrix,
              std::bind(VintfObject::GetFrameworkCompatibilityMatrix, true /* skipCache */))) !=
         OK) {
         return status;
     }
     if ((status = getMissing(
-             pkg.dev.matrix.get(), mount, mountVendor, &updated.dev.matrix,
+             pkg.dev.matrix, mount, mountVendor, &updated.dev.matrix,
              std::bind(VintfObject::GetDeviceCompatibilityMatrix, true /* skipCache */))) != OK) {
         return status;
     }
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index 9d5cc6f..a099912 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_VINTF_VINTF_OBJECT_H_
 #define ANDROID_VINTF_VINTF_OBJECT_H_
 
+#include <memory>
+
 #include "CompatibilityMatrix.h"
 #include "HalManifest.h"
 #include "RuntimeInfo.h"
@@ -53,30 +55,32 @@
      * Return the API that access the device-side HAL manifest stored
      * in /vendor/manifest.xml.
      */
-    static const HalManifest *GetDeviceHalManifest(bool skipCache = false);
+    static std::shared_ptr<const HalManifest> GetDeviceHalManifest(bool skipCache = false);
 
     /*
      * Return the API that access the framework-side HAL manifest stored
      * in /system/manfiest.xml.
      */
-    static const HalManifest *GetFrameworkHalManifest(bool skipCache = false);
+    static 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.
      */
-    static const CompatibilityMatrix *GetDeviceCompatibilityMatrix(bool skipCache = false);
+    static std::shared_ptr<const CompatibilityMatrix> GetDeviceCompatibilityMatrix(
+        bool skipCache = false);
 
     /*
-     * Return the API that access the device-side compatibility matrix stored
+     * Return the API that access the framework-side compatibility matrix stored
      * in /system/compatibility_matrix.xml.
      */
-    static const CompatibilityMatrix *GetFrameworkCompatibilityMatrix(bool skipCache = false);
+    static std::shared_ptr<const CompatibilityMatrix> GetFrameworkCompatibilityMatrix(
+        bool skipCache = false);
 
     /*
      * Return the API that access device runtime info.
      */
-    static const RuntimeInfo *GetRuntimeInfo(bool skipCache = false);
+    static std::shared_ptr<const RuntimeInfo> GetRuntimeInfo(bool skipCache = false);
 
     /**
      * Check compatibility, given a set of manifests / matrices in packageInfo.
diff --git a/main.cpp b/main.cpp
index 01e3ea0..e4b8f6b 100644
--- a/main.cpp
+++ b/main.cpp
@@ -25,31 +25,31 @@
 
     std::cout << "======== Device HAL Manifest =========" << std::endl;
 
-    const HalManifest *vm = VintfObject::GetDeviceHalManifest();
+    std::shared_ptr<const HalManifest> vm = VintfObject::GetDeviceHalManifest();
     if (vm != nullptr)
         std::cout << gHalManifestConverter(*vm);
 
     std::cout << "======== Framework HAL Manifest =========" << std::endl;
 
-    const HalManifest *fm = VintfObject::GetFrameworkHalManifest();
+    std::shared_ptr<const HalManifest> fm = VintfObject::GetFrameworkHalManifest();
     if (fm != nullptr)
         std::cout << gHalManifestConverter(*fm);
 
     std::cout << "======== Device Compatibility Matrix =========" << std::endl;
 
-    const CompatibilityMatrix *vcm = VintfObject::GetDeviceCompatibilityMatrix();
+    std::shared_ptr<const CompatibilityMatrix> vcm = VintfObject::GetDeviceCompatibilityMatrix();
     if (vcm != nullptr)
         std::cout << gCompatibilityMatrixConverter(*vcm);
 
     std::cout << "======== Framework Compatibility Matrix =========" << std::endl;
 
-    const CompatibilityMatrix *fcm = VintfObject::GetFrameworkCompatibilityMatrix();
+    std::shared_ptr<const CompatibilityMatrix> fcm = VintfObject::GetFrameworkCompatibilityMatrix();
     if (fcm != nullptr)
         std::cout << gCompatibilityMatrixConverter(*fcm);
 
     std::cout << "======== Runtime Info =========" << std::endl;
 
-    const RuntimeInfo* ki = VintfObject::GetRuntimeInfo();
+    std::shared_ptr<const RuntimeInfo> ki = VintfObject::GetRuntimeInfo();
     if (ki != nullptr) std::cout << dump(*ki);
     std::cout << std::endl;