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/RuntimeInfo-host.cpp b/RuntimeInfo-host.cpp
index 96eff42..bd46a9f 100644
--- a/RuntimeInfo-host.cpp
+++ b/RuntimeInfo-host.cpp
@@ -23,7 +23,7 @@
namespace android {
namespace vintf {
-status_t RuntimeInfo::fetchAllInformation() {
+status_t RuntimeInfo::fetchAllInformation(RuntimeInfo::FetchFlags /* flags */) {
LOG(WARNING) << "Should not run fetchAllInformation on host.";
return OK;
}
diff --git a/RuntimeInfo-target.cpp b/RuntimeInfo-target.cpp
index 9518a0c..1bdf2c3 100644
--- a/RuntimeInfo-target.cpp
+++ b/RuntimeInfo-target.cpp
@@ -45,8 +45,9 @@
struct RuntimeInfoFetcher {
RuntimeInfoFetcher(RuntimeInfo *ki) : mRuntimeInfo(ki) { }
- status_t fetchAllInformation();
-private:
+ status_t fetchAllInformation(RuntimeInfo::FetchFlags flags);
+
+ private:
status_t fetchVersion();
status_t fetchKernelConfigs();
status_t fetchCpuInfo();
@@ -159,28 +160,31 @@
return OK;
}
-status_t RuntimeInfoFetcher::fetchAllInformation() {
+status_t RuntimeInfoFetcher::fetchAllInformation(RuntimeInfo::FetchFlags flags) {
+
+ using F = RuntimeInfo::FetchFlag;
+ using RF = RuntimeInfoFetcher;
+ using FetchFunction = status_t(RF::*)();
+ const static std::vector<std::tuple<F, FetchFunction, std::string>> gFetchFunctions({
+ // flag fetch function description
+ {F::CPU_VERSION, &RF::fetchVersion, "/proc/version"},
+ {F::CONFIG_GZ, &RF::fetchKernelConfigs, "/proc/config.gz"},
+ {F::CPU_INFO, &RF::fetchCpuInfo, "/proc/cpuinfo"},
+ {F::POLICYVERS, &RF::fetchKernelSepolicyVers, "kernel sepolicy version"},
+ {F::AVB, &RF::fetchAvb, "avb version"},
+ });
+
status_t err;
- if ((err = fetchVersion()) != OK) {
- LOG(WARNING) << "Cannot fetch or parse /proc/version: " << strerror(-err);
- }
- if ((err = fetchKernelConfigs()) != OK) {
- LOG(WARNING) << "Cannot fetch or parse /proc/config.gz: " << strerror(-err);
- }
- if ((err = fetchCpuInfo()) != OK) {
- LOG(WARNING) << "Cannot fetch /proc/cpuinfo: " << strerror(-err);
- }
- if ((err = fetchKernelSepolicyVers()) != OK) {
- LOG(WARNING) << "Cannot fetch kernel sepolicy version: " << strerror(-err);
- }
- if ((err = fetchAvb()) != OK) {
- LOG(WARNING) << "Cannot fetch sepolicy avb version: " << strerror(-err);
- }
+ for (const auto& tuple : gFetchFunctions)
+ if ((flags & std::get<0>(tuple)) && (err = (*this.*std::get<1>(tuple))()) != OK)
+ LOG(WARNING) << "Cannot fetch or parse " << std::get<2>(tuple) << ": "
+ << strerror(-err);
+
return OK;
}
-status_t RuntimeInfo::fetchAllInformation() {
- return RuntimeInfoFetcher(this).fetchAllInformation();
+status_t RuntimeInfo::fetchAllInformation(RuntimeInfo::FetchFlags flags) {
+ return RuntimeInfoFetcher(this).fetchAllInformation(flags);
}
} // namespace vintf
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 {
diff --git a/include/vintf/RuntimeInfo.h b/include/vintf/RuntimeInfo.h
index 1505c15..390e3ed 100644
--- a/include/vintf/RuntimeInfo.h
+++ b/include/vintf/RuntimeInfo.h
@@ -74,13 +74,26 @@
bool checkCompatibility(const CompatibilityMatrix& mat, std::string* error = nullptr,
DisabledChecks disabledChecks = ENABLE_ALL_CHECKS) const;
+ using FetchFlags = uint32_t;
+ enum FetchFlag : FetchFlags {
+ CPU_VERSION = 1 << 0,
+ CONFIG_GZ = 1 << 1,
+ CPU_INFO = 1 << 2,
+ POLICYVERS = 1 << 3,
+ AVB = 1 << 4,
+ LAST_PLUS_ONE,
+
+ NONE = 0,
+ ALL = ((LAST_PLUS_ONE - 1) << 1) - 1,
+ };
+
private:
friend struct RuntimeInfoFetcher;
friend class VintfObject;
friend struct LibVintfTest;
friend std::string dump(const RuntimeInfo &ki);
- status_t fetchAllInformation();
+ status_t fetchAllInformation(FetchFlags flags);
// mKernelVersion = x'.y'.z', minLts = x.y.z,
// match if x == x' , y == y' , and z <= z'.
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index fe70784..5593da5 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -80,8 +80,19 @@
/*
* 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
*/
- static std::shared_ptr<const RuntimeInfo> GetRuntimeInfo(bool skipCache = false);
+ static 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.