Allow RuntimeInfo::fetch to fetch conditionally

... to avoid unnecessary denials if the caller process does
not have enough permissions.

Test: CtsDeviceInfo
Bug: 66960848
Change-Id: I5555307ff086fbc10cfa677c530dc3de673e18f6
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 92fa0b0..e87dd05 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -33,6 +33,12 @@
     std::mutex mutex;
 };
 
+struct LockedRuntimeInfoCache {
+    std::shared_ptr<RuntimeInfo> object;
+    std::mutex mutex;
+    RuntimeInfo::FetchFlags fetchedFlags = RuntimeInfo::FetchFlag::NONE;
+};
+
 template <typename T, typename F>
 static std::shared_ptr<const T> Get(
         LockedSharedPtr<T> *ptr,
@@ -82,10 +88,27 @@
 }
 
 // static
-std::shared_ptr<const RuntimeInfo> VintfObject::GetRuntimeInfo(bool skipCache) {
-    static LockedSharedPtr<RuntimeInfo> gDeviceRuntimeInfo;
-    return Get(&gDeviceRuntimeInfo, skipCache,
-            std::bind(&RuntimeInfo::fetchAllInformation, std::placeholders::_1));
+std::shared_ptr<const RuntimeInfo> VintfObject::GetRuntimeInfo(bool skipCache,
+                                                               RuntimeInfo::FetchFlags flags) {
+    static LockedRuntimeInfoCache gDeviceRuntimeInfo;
+    std::unique_lock<std::mutex> _lock(gDeviceRuntimeInfo.mutex);
+
+    if (!skipCache) {
+        flags &= (~gDeviceRuntimeInfo.fetchedFlags);
+    }
+
+    if (gDeviceRuntimeInfo.object == nullptr) {
+        gDeviceRuntimeInfo.object = std::make_shared<RuntimeInfo>();
+    }
+
+    status_t status = gDeviceRuntimeInfo.object->fetchAllInformation(flags);
+    if (status != OK) {
+        gDeviceRuntimeInfo.fetchedFlags &= (~flags);  // mark the fields as "not fetched"
+        return nullptr;
+    }
+
+    gDeviceRuntimeInfo.fetchedFlags |= flags;
+    return gDeviceRuntimeInfo.object;
 }
 
 namespace details {