summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.bp89
-rw-r--r--RuntimeInfo-host.cpp2
-rw-r--r--RuntimeInfo-target.cpp7
-rw-r--r--VintfObject.cpp65
-rw-r--r--VintfObjectRecovery.cpp5
-rw-r--r--check_vintf.cpp263
-rw-r--r--include/vintf/DisabledChecks.h2
-rw-r--r--include/vintf/MapValueIterator.h20
-rw-r--r--include/vintf/RuntimeInfo.h1
-rw-r--r--include/vintf/VintfObject.h10
-rw-r--r--test/Android.bp5
-rw-r--r--test/RuntimeInfo-fake.cpp12
-rw-r--r--test/utils-fake.cpp14
-rw-r--r--test/utils-fake.h18
-rw-r--r--test/vintf_object_tests.cpp14
-rw-r--r--utils-common.cpp42
-rw-r--r--utils.cpp30
-rw-r--r--utils.h12
18 files changed, 488 insertions, 123 deletions
diff --git a/Android.bp b/Android.bp
index 375246c..1c7a420 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,8 +24,10 @@ cc_defaults {
24 ], 24 ],
25} 25}
26 26
27cc_defaults { 27cc_library_static {
28 name: "libvintf-common-srcs", 28 name: "libvintf_common",
29 defaults: ["libvintf-defaults"],
30 host_supported: true,
29 srcs: [ 31 srcs: [
30 "parse_string.cpp", 32 "parse_string.cpp",
31 "parse_xml.cpp", 33 "parse_xml.cpp",
@@ -33,6 +35,7 @@ cc_defaults {
33 "HalManifest.cpp", 35 "HalManifest.cpp",
34 "HalInterface.cpp", 36 "HalInterface.cpp",
35 "KernelConfigTypedValue.cpp", 37 "KernelConfigTypedValue.cpp",
38 "KernelConfigParser.cpp",
36 "RuntimeInfo.cpp", 39 "RuntimeInfo.cpp",
37 "ManifestHal.cpp", 40 "ManifestHal.cpp",
38 "MatrixHal.cpp", 41 "MatrixHal.cpp",
@@ -41,47 +44,55 @@ cc_defaults {
41 "TransportArch.cpp", 44 "TransportArch.cpp",
42 "VintfObject.cpp", 45 "VintfObject.cpp",
43 "XmlFile.cpp", 46 "XmlFile.cpp",
44 ] 47 "utils-common.cpp",
45} 48 ],
46
47cc_library {
48 name: "libvintf",
49 host_supported: true,
50 defaults: ["libvintf-defaults", "libvintf-common-srcs"],
51 shared_libs: [ 49 shared_libs: [
52 "libbase", 50 "libbase",
53 "liblog", 51 "liblog",
54 "libselinux", 52 "libselinux",
55 "libtinyxml2", 53 "libtinyxml2",
54 "libz",
56 ], 55 ],
57 export_include_dirs: ["include"], 56 export_include_dirs: ["include", "."],
58 local_include_dirs: ["include/vintf"], 57 local_include_dirs: ["include/vintf"],
59 58
60 srcs: [
61 "KernelConfigParser.cpp",
62 "utils.cpp",
63 ],
64
65 target: { 59 target: {
66 host: { 60 host: {
67 srcs: [ 61 srcs: [
68 "RuntimeInfo-host.cpp" 62 "RuntimeInfo-host.cpp",
69 ], 63 ],
70 }, 64 },
71 android: { 65 android: {
72 shared_libs: [
73 "libcutils",
74 "libutils",
75 "libz"
76 ],
77 srcs: [ 66 srcs: [
78 "RuntimeInfo-target.cpp" 67 "RuntimeInfo-target.cpp",
79 ], 68 ],
80 cflags: ["-DLIBVINTF_TARGET"], 69 cflags: ["-DLIBVINTF_TARGET"],
81 }, 70 },
82 } 71 }
83} 72}
84 73
74// libvintf_common + utils.cpp
75cc_library {
76 name: "libvintf",
77 host_supported: true,
78 defaults: ["libvintf-defaults"],
79 shared_libs: [
80 "libbase",
81 "liblog",
82 "libselinux",
83 "libtinyxml2",
84 "libz",
85 ],
86 export_include_dirs: ["include"],
87 local_include_dirs: ["include/vintf"],
88
89 srcs: [
90 "utils.cpp",
91 ],
92
93 whole_static_libs: ["libvintf_common"],
94}
95
85cc_binary { 96cc_binary {
86 name: "vintf", 97 name: "vintf",
87 defaults: ["libvintf-defaults"], 98 defaults: ["libvintf-defaults"],
@@ -98,7 +109,8 @@ cc_binary_host {
98 name: "checkvintf", 109 name: "checkvintf",
99 defaults: ["libvintf-defaults"], 110 defaults: ["libvintf-defaults"],
100 static_libs: [ 111 static_libs: [
101 "libvintf", 112 "libvintf_common",
113 "libutils",
102 "libtinyxml2", 114 "libtinyxml2",
103 ], 115 ],
104 shared_libs: [ 116 shared_libs: [
@@ -106,7 +118,6 @@ cc_binary_host {
106 ], 118 ],
107 srcs: [ 119 srcs: [
108 "check_vintf.cpp", 120 "check_vintf.cpp",
109 "utils.cpp"
110 ], 121 ],
111} 122}
112 123
@@ -138,33 +149,3 @@ cc_binary_host {
138 "assemble_vintf_main.cpp" 149 "assemble_vintf_main.cpp"
139 ], 150 ],
140} 151}
141
142cc_library_static {
143 name: "libvintftest",
144 defaults: ["libvintf-defaults", "libvintf-common-srcs"],
145 host_supported: true,
146 shared_libs: [
147 "libbase",
148 "liblog",
149 "libselinux",
150 "libtinyxml2",
151 ],
152 export_include_dirs: ["include/vintf", "include", "test", "."],
153 local_include_dirs: ["include/vintf", "test", "."],
154
155 srcs: [
156 "test/RuntimeInfo-fake.cpp",
157 "test/utils-fake.cpp",
158 ],
159
160 target: {
161 android: {
162 shared_libs: [
163 "libcutils",
164 "libutils",
165 "libz"
166 ],
167 cflags: ["-DLIBVINTF_TARGET"],
168 },
169 }
170}
diff --git a/RuntimeInfo-host.cpp b/RuntimeInfo-host.cpp
index bd46a9f..e66e6f4 100644
--- a/RuntimeInfo-host.cpp
+++ b/RuntimeInfo-host.cpp
@@ -18,7 +18,7 @@
18#define LOG_TAG "libvintf" 18#define LOG_TAG "libvintf"
19#include <android-base/logging.h> 19#include <android-base/logging.h>
20 20
21#include "RuntimeInfo.h" 21#include <vintf/RuntimeInfo.h>
22 22
23namespace android { 23namespace android {
24namespace vintf { 24namespace vintf {
diff --git a/RuntimeInfo-target.cpp b/RuntimeInfo-target.cpp
index 1bdf2c3..6f2e9e8 100644
--- a/RuntimeInfo-target.cpp
+++ b/RuntimeInfo-target.cpp
@@ -33,7 +33,7 @@
33#include <iostream> 33#include <iostream>
34#include <sstream> 34#include <sstream>
35 35
36#include <cutils/properties.h> 36#include <android-base/properties.h>
37#include <selinux/selinux.h> 37#include <selinux/selinux.h>
38#include <zlib.h> 38#include <zlib.h>
39 39
@@ -148,12 +148,11 @@ status_t RuntimeInfoFetcher::parseKernelVersion() {
148} 148}
149 149
150status_t RuntimeInfoFetcher::fetchAvb() { 150status_t RuntimeInfoFetcher::fetchAvb() {
151 char prop[PROPERTY_VALUE_MAX]; 151 std::string prop = android::base::GetProperty("ro.boot.vbmeta.avb_version", "0.0");
152 property_get("ro.boot.vbmeta.avb_version", prop, "0.0");
153 if (!parse(prop, &mRuntimeInfo->mBootVbmetaAvbVersion)) { 152 if (!parse(prop, &mRuntimeInfo->mBootVbmetaAvbVersion)) {
154 return UNKNOWN_ERROR; 153 return UNKNOWN_ERROR;
155 } 154 }
156 property_get("ro.boot.avb_version", prop, "0.0"); 155 prop = android::base::GetProperty("ro.boot.avb_version", "0.0");
157 if (!parse(prop, &mRuntimeInfo->mBootAvbVersion)) { 156 if (!parse(prop, &mRuntimeInfo->mBootAvbVersion)) {
158 return UNKNOWN_ERROR; 157 return UNKNOWN_ERROR;
159 } 158 }
diff --git a/VintfObject.cpp b/VintfObject.cpp
index c66011b..c10949c 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -27,10 +27,6 @@
27#include <memory> 27#include <memory>
28#include <mutex> 28#include <mutex>
29 29
30#ifdef LIBVINTF_TARGET
31#include <android-base/properties.h>
32#endif
33
34#include <android-base/logging.h> 30#include <android-base/logging.h>
35 31
36using std::placeholders::_1; 32using std::placeholders::_1;
@@ -81,8 +77,7 @@ std::shared_ptr<const HalManifest> VintfObject::GetDeviceHalManifest(bool skipCa
81// static 77// static
82std::shared_ptr<const HalManifest> VintfObject::GetFrameworkHalManifest(bool skipCache) { 78std::shared_ptr<const HalManifest> VintfObject::GetFrameworkHalManifest(bool skipCache) {
83 static LockedSharedPtr<HalManifest> gFrameworkManifest; 79 static LockedSharedPtr<HalManifest> gFrameworkManifest;
84 return Get(&gFrameworkManifest, skipCache, 80 return Get(&gFrameworkManifest, skipCache, &VintfObject::FetchFrameworkHalManifest);
85 std::bind(&HalManifest::fetchAllInformation, _1, kSystemManifest, _2));
86} 81}
87 82
88 83
@@ -129,15 +124,12 @@ status_t VintfObject::GetCombinedFrameworkMatrix(
129 } 124 }
130 125
131 // TODO(b/70628538): Do not infer from Shipping API level. 126 // TODO(b/70628538): Do not infer from Shipping API level.
132#ifdef LIBVINTF_TARGET
133 if (deviceLevel == Level::UNSPECIFIED) { 127 if (deviceLevel == Level::UNSPECIFIED) {
134 auto shippingApi = 128 auto shippingApi = getPropertyFetcher().getUintProperty("ro.product.first_api_level", 0u);
135 android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0u);
136 if (shippingApi != 0u) { 129 if (shippingApi != 0u) {
137 deviceLevel = details::convertFromApiLevel(shippingApi); 130 deviceLevel = details::convertFromApiLevel(shippingApi);
138 } 131 }
139 } 132 }
140#endif
141 133
142 if (deviceLevel == Level::UNSPECIFIED) { 134 if (deviceLevel == Level::UNSPECIFIED) {
143 // Cannot infer FCM version. Combine all matrices by assuming 135 // Cannot infer FCM version. Combine all matrices by assuming
@@ -216,9 +208,8 @@ status_t VintfObject::FetchDeviceHalManifest(HalManifest* out, std::string* erro
216status_t VintfObject::FetchOdmHalManifest(HalManifest* out, std::string* error) { 208status_t VintfObject::FetchOdmHalManifest(HalManifest* out, std::string* error) {
217 status_t status; 209 status_t status;
218 210
219#ifdef LIBVINTF_TARGET
220 std::string productModel; 211 std::string productModel;
221 productModel = android::base::GetProperty("ro.boot.product.hardware.sku", ""); 212 productModel = getPropertyFetcher().getProperty("ro.boot.product.hardware.sku", "");
222 213
223 if (!productModel.empty()) { 214 if (!productModel.empty()) {
224 status = 215 status =
@@ -227,14 +218,12 @@ status_t VintfObject::FetchOdmHalManifest(HalManifest* out, std::string* error)
227 return status; 218 return status;
228 } 219 }
229 } 220 }
230#endif
231 221
232 status = FetchOneHalManifest(kOdmManifest, out, error); 222 status = FetchOneHalManifest(kOdmManifest, out, error);
233 if (status == OK || status != NAME_NOT_FOUND) { 223 if (status == OK || status != NAME_NOT_FOUND) {
234 return status; 224 return status;
235 } 225 }
236 226
237#ifdef LIBVINTF_TARGET
238 if (!productModel.empty()) { 227 if (!productModel.empty()) {
239 status = FetchOneHalManifest(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml", out, 228 status = FetchOneHalManifest(kOdmLegacyVintfDir + "manifest_" + productModel + ".xml", out,
240 error); 229 error);
@@ -242,7 +231,6 @@ status_t VintfObject::FetchOdmHalManifest(HalManifest* out, std::string* error)
242 return status; 231 return status;
243 } 232 }
244 } 233 }
245#endif
246 234
247 status = FetchOneHalManifest(kOdmLegacyManifest, out, error); 235 status = FetchOneHalManifest(kOdmLegacyManifest, out, error);
248 if (status == OK || status != NAME_NOT_FOUND) { 236 if (status == OK || status != NAME_NOT_FOUND) {
@@ -273,6 +261,15 @@ status_t VintfObject::FetchDeviceMatrix(CompatibilityMatrix* out, std::string* e
273 return out->fetchAllInformation(kVendorLegacyMatrix, error); 261 return out->fetchAllInformation(kVendorLegacyMatrix, error);
274} 262}
275 263
264status_t VintfObject::FetchFrameworkHalManifest(HalManifest* out, std::string* error) {
265 HalManifest etcManifest;
266 if (etcManifest.fetchAllInformation(kSystemManifest, error) == OK) {
267 *out = std::move(etcManifest);
268 return OK;
269 }
270 return out->fetchAllInformation(kSystemLegacyManifest, error);
271}
272
276std::vector<Named<CompatibilityMatrix>> VintfObject::GetAllFrameworkMatrixLevels( 273std::vector<Named<CompatibilityMatrix>> VintfObject::GetAllFrameworkMatrixLevels(
277 std::string* error) { 274 std::string* error) {
278 std::vector<std::string> fileNames; 275 std::vector<std::string> fileNames;
@@ -289,7 +286,7 @@ std::vector<Named<CompatibilityMatrix>> VintfObject::GetAllFrameworkMatrixLevels
289 status_t status = details::gFetcher->fetch(path, content, &fetchError); 286 status_t status = details::gFetcher->fetch(path, content, &fetchError);
290 if (status != OK) { 287 if (status != OK) {
291 if (error) { 288 if (error) {
292 *error += "Ignore file " + path + ": " + fetchError + "\n"; 289 *error += "Framework Matrix: Ignore file " + path + ": " + fetchError + "\n";
293 } 290 }
294 continue; 291 continue;
295 } 292 }
@@ -297,7 +294,7 @@ std::vector<Named<CompatibilityMatrix>> VintfObject::GetAllFrameworkMatrixLevels
297 auto it = results.emplace(results.end()); 294 auto it = results.emplace(results.end());
298 if (!gCompatibilityMatrixConverter(&it->object, content, error)) { 295 if (!gCompatibilityMatrixConverter(&it->object, content, error)) {
299 if (error) { 296 if (error) {
300 *error += "Ignore file " + path + ": " + *error + "\n"; 297 *error += "Framework Matrix: Ignore file " + path + ": " + *error + "\n";
301 } 298 }
302 results.erase(it); 299 results.erase(it);
303 continue; 300 continue;
@@ -487,7 +484,9 @@ int32_t checkCompatibility(const std::vector<std::string>& xmls, bool mount,
487 (void)mounter.umountVendor(); // ignore errors 484 (void)mounter.umountVendor(); // ignore errors
488 } 485 }
489 486
490 updated.runtimeInfo = VintfObject::GetRuntimeInfo(true /* skipCache */); 487 if ((disabledChecks & DISABLE_RUNTIME_INFO) == 0) {
488 updated.runtimeInfo = VintfObject::GetRuntimeInfo(true /* skipCache */);
489 }
491 490
492 // null checks for files and runtime info after the update 491 // null checks for files and runtime info after the update
493 if (updated.fwk.manifest == nullptr) { 492 if (updated.fwk.manifest == nullptr) {
@@ -506,9 +505,12 @@ int32_t checkCompatibility(const std::vector<std::string>& xmls, bool mount,
506 ADD_MESSAGE("No device matrix file from device or from update package"); 505 ADD_MESSAGE("No device matrix file from device or from update package");
507 return NO_INIT; 506 return NO_INIT;
508 } 507 }
509 if (updated.runtimeInfo == nullptr) { 508
510 ADD_MESSAGE("No runtime info from device"); 509 if ((disabledChecks & DISABLE_RUNTIME_INFO) == 0) {
511 return NO_INIT; 510 if (updated.runtimeInfo == nullptr) {
511 ADD_MESSAGE("No runtime info from device");
512 return NO_INIT;
513 }
512 } 514 }
513 515
514 // compatiblity check. 516 // compatiblity check.
@@ -526,11 +528,15 @@ int32_t checkCompatibility(const std::vector<std::string>& xmls, bool mount,
526 } 528 }
527 return INCOMPATIBLE; 529 return INCOMPATIBLE;
528 } 530 }
529 if (!updated.runtimeInfo->checkCompatibility(*updated.fwk.matrix, error, disabledChecks)) { 531
530 if (error) { 532 if ((disabledChecks & DISABLE_RUNTIME_INFO) == 0) {
531 error->insert(0, "Runtime info and framework compatibility matrix are incompatible: "); 533 if (!updated.runtimeInfo->checkCompatibility(*updated.fwk.matrix, error, disabledChecks)) {
534 if (error) {
535 error->insert(0,
536 "Runtime info and framework compatibility matrix are incompatible: ");
537 }
538 return INCOMPATIBLE;
532 } 539 }
533 return INCOMPATIBLE;
534 } 540 }
535 541
536 return COMPATIBLE; 542 return COMPATIBLE;
@@ -547,10 +553,19 @@ const std::string kOdmManifest = kOdmVintfDir + "manifest.xml";
547 553
548const std::string kVendorLegacyManifest = "/vendor/manifest.xml"; 554const std::string kVendorLegacyManifest = "/vendor/manifest.xml";
549const std::string kVendorLegacyMatrix = "/vendor/compatibility_matrix.xml"; 555const std::string kVendorLegacyMatrix = "/vendor/compatibility_matrix.xml";
556const std::string kSystemLegacyManifest = "/system/manifest.xml";
550const std::string kSystemLegacyMatrix = "/system/compatibility_matrix.xml"; 557const std::string kSystemLegacyMatrix = "/system/compatibility_matrix.xml";
551const std::string kOdmLegacyVintfDir = "/odm/etc/"; 558const std::string kOdmLegacyVintfDir = "/odm/etc/";
552const std::string kOdmLegacyManifest = kOdmLegacyVintfDir + "manifest.xml"; 559const std::string kOdmLegacyManifest = kOdmLegacyVintfDir + "manifest.xml";
553 560
561std::vector<std::string> dumpFileList() {
562 return {
563 kSystemVintfDir, kVendorVintfDir, kOdmVintfDir, kOdmLegacyVintfDir,
564
565 kVendorLegacyManifest, kVendorLegacyMatrix, kSystemLegacyManifest, kSystemLegacyMatrix,
566 };
567}
568
554} // namespace details 569} // namespace details
555 570
556// static 571// static
diff --git a/VintfObjectRecovery.cpp b/VintfObjectRecovery.cpp
index 59fe6da..9d7cab7 100644
--- a/VintfObjectRecovery.cpp
+++ b/VintfObjectRecovery.cpp
@@ -16,7 +16,6 @@
16 16
17#include "VintfObjectRecovery.h" 17#include "VintfObjectRecovery.h"
18 18
19#include <android-base/properties.h>
20#include <sys/mount.h> 19#include <sys/mount.h>
21#include <fs_mgr.h> 20#include <fs_mgr.h>
22 21
@@ -48,7 +47,7 @@ class RecoveryPartitionMounter : public PartitionMounter {
48 if (fstab == NULL) { 47 if (fstab == NULL) {
49 return UNKNOWN_ERROR; 48 return UNKNOWN_ERROR;
50 } 49 }
51 if (android::base::GetBoolProperty("ro.build.system_root_image", false)) { 50 if (getPropertyFetcher().getBoolProperty("ro.build.system_root_image", false)) {
52 return mountAt(fstab, "/", "/system_root"); 51 return mountAt(fstab, "/", "/system_root");
53 } else { 52 } else {
54 return mountAt(fstab, "/system", "/system"); 53 return mountAt(fstab, "/system", "/system");
@@ -64,7 +63,7 @@ class RecoveryPartitionMounter : public PartitionMounter {
64 } 63 }
65 64
66 status_t umountSystem() const override { 65 status_t umountSystem() const override {
67 if (android::base::GetBoolProperty("ro.build.system_root_image", false)) { 66 if (getPropertyFetcher().getBoolProperty("ro.build.system_root_image", false)) {
68 return umount("/system_root"); 67 return umount("/system_root");
69 } else { 68 } else {
70 return umount("/system"); 69 return umount("/system");
diff --git a/check_vintf.cpp b/check_vintf.cpp
index f64f81d..6acc311 100644
--- a/check_vintf.cpp
+++ b/check_vintf.cpp
@@ -14,14 +14,119 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include <getopt.h>
18#include <unistd.h>
19
17#include <iostream> 20#include <iostream>
21#include <map>
18 22
23#include <android-base/parseint.h>
24#include <utils/Errors.h>
25#include <vintf/VintfObject.h>
19#include <vintf/parse_xml.h> 26#include <vintf/parse_xml.h>
20#include "utils.h" 27#include "utils.h"
21 28
22namespace android { 29namespace android {
23namespace vintf { 30namespace vintf {
31namespace details {
32
33// fake sysprops
34using Properties = std::map<std::string, std::string>;
35
36enum Option : int {
37 DUMP_FILE_LIST = 1,
38 ROOTDIR,
39 HELP,
40 PROPERTY,
41 CHECK_COMPAT,
42};
43// command line arguments
44using Args = std::multimap<Option, std::string>;
45
46class HostFileFetcher : public FileFetcher {
47 public:
48 void setRootDir(const std::string& rootdir) {
49 mRootDir = rootdir;
50 if (!mRootDir.empty() && mRootDir.back() != '/') {
51 mRootDir.push_back('/');
52 }
53 }
54 virtual status_t fetch(const std::string& path, std::string& fetched, std::string* error) {
55 return HostFileFetcher::fetchInternal(path, fetched, error);
56 }
57 virtual status_t fetch(const std::string& path, std::string& fetched) {
58 return HostFileFetcher::fetchInternal(path, fetched, nullptr);
59 }
60 virtual status_t listFiles(const std::string& path, std::vector<std::string>* out,
61 std::string* error) {
62 status_t status = FileFetcher::listFiles(mRootDir + path, out, error);
63 std::cerr << "Debug: List '" << mRootDir << path << "': " << toString(status) << std::endl;
64 return status;
65 }
66
67 private:
68 status_t fetchInternal(const std::string& path, std::string& fetched, std::string* error) {
69 status_t status = FileFetcher::fetchInternal(mRootDir + path, fetched, error);
70 std::cerr << "Debug: Fetch '" << mRootDir << path << "': " << toString(status) << std::endl;
71 return status;
72 }
73 static std::string toString(status_t status) {
74 return status == OK ? "SUCCESS" : strerror(-status);
75 }
76 std::string mRootDir;
77};
78
79class PresetPropertyFetcher : public PropertyFetcher {
80 public:
81 std::string getProperty(const std::string& key,
82 const std::string& defaultValue) const override {
83 auto it = mProps.find(key);
84 if (it == mProps.end()) {
85 std::cerr << "Debug: Sysprop " << key << " is missing, default to '" << defaultValue
86 << "'" << std::endl;
87 return defaultValue;
88 }
89 std::cerr << "Debug: Sysprop " << key << "=" << it->second << std::endl;
90 return it->second;
91 }
92 uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
93 uint64_t max) const override {
94 uint64_t result;
95 std::string value = getProperty(key, "");
96 if (!value.empty() && android::base::ParseUint(value, &result, max)) return result;
97 return defaultValue;
98 }
99 bool getBoolProperty(const std::string& key, bool defaultValue) const override {
100 std::string value = getProperty(key, "");
101 if (value == "1" || value == "true") {
102 return true;
103 } else if (value == "0" || value == "false") {
104 return false;
105 }
106 return defaultValue;
107 }
108 void setProperties(const Properties& props) { mProps.insert(props.begin(), props.end()); }
109
110 private:
111 std::map<std::string, std::string> mProps;
112};
24 113
114// globals
115static HostFileFetcher hostFileFetcher;
116FileFetcher* gFetcher = &hostFileFetcher;
117
118static PartitionMounter partitionMounter;
119PartitionMounter* gPartitionMounter = &partitionMounter;
120
121static ObjectFactory<RuntimeInfo> runtimeInfoFactory;
122ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = &runtimeInfoFactory;
123
124static PresetPropertyFetcher hostPropertyFetcher;
125const PropertyFetcher& getPropertyFetcher() {
126 return hostPropertyFetcher;
127}
128
129// helper functions
25template <typename T> 130template <typename T>
26std::unique_ptr<T> readObject(const std::string& path, const XmlConverter<T>& converter) { 131std::unique_ptr<T> readObject(const std::string& path, const XmlConverter<T>& converter) {
27 std::string xml; 132 std::string xml;
@@ -40,20 +145,9 @@ std::unique_ptr<T> readObject(const std::string& path, const XmlConverter<T>& co
40 return ret; 145 return ret;
41} 146}
42 147
43} // namespace vintf 148int checkCompatibilityForFiles(const std::string& manifestPath, const std::string& matrixPath) {
44} // namespace android 149 auto manifest = readObject(manifestPath, gHalManifestConverter);
45 150 auto matrix = readObject(matrixPath, gCompatibilityMatrixConverter);
46int main(int argc, char** argv) {
47 using namespace android::vintf;
48 if (argc < 3) {
49 std::cerr << "usage: " << argv[0] << " <manifest.xml> <matrix.xml>" << std::endl
50 << " Checks compatibility between a manifest and a compatibility matrix."
51 << std::endl;
52 return -1;
53 }
54
55 auto manifest = readObject(argv[1], gHalManifestConverter);
56 auto matrix = readObject(argv[2], gCompatibilityMatrixConverter);
57 if (manifest == nullptr || matrix == nullptr) { 151 if (manifest == nullptr || matrix == nullptr) {
58 return -1; 152 return -1;
59 } 153 }
@@ -68,3 +162,144 @@ int main(int argc, char** argv) {
68 std::cout << "true" << std::endl; 162 std::cout << "true" << std::endl;
69 return 0; 163 return 0;
70} 164}
165
166Args parseArgs(int argc, char** argv) {
167 int longOptFlag;
168 int optionIndex;
169 Args ret;
170 std::vector<struct option> longopts{
171 {"dump-file-list", no_argument, &longOptFlag, DUMP_FILE_LIST},
172 {"rootdir", required_argument, &longOptFlag, ROOTDIR},
173 {"help", no_argument, &longOptFlag, HELP},
174 {"property", required_argument, &longOptFlag, PROPERTY},
175 {"check-compat", no_argument, &longOptFlag, CHECK_COMPAT},
176 {0, 0, 0, 0}};
177 std::map<int, Option> shortopts{
178 {'h', HELP}, {'D', PROPERTY}, {'c', CHECK_COMPAT},
179 };
180 for (;;) {
181 int c = getopt_long(argc, argv, "hcD:", longopts.data(), &optionIndex);
182 if (c == -1) {
183 break;
184 }
185 std::string argValue = optarg ? optarg : std::string{};
186 if (c == 0) {
187 ret.emplace(static_cast<Option>(longOptFlag), std::move(argValue));
188 } else {
189 ret.emplace(shortopts[c], std::move(argValue));
190 }
191 }
192 if (optind < argc) {
193 // see non option
194 std::cerr << "unrecognized option `" << argv[optind] << "'" << std::endl;
195 return {{HELP, ""}};
196 }
197 return ret;
198}
199
200template <typename T>
201Properties getProperties(const T& args) {
202 Properties ret;
203 for (const auto& arg : args) {
204 auto pos = arg.find('=');
205 auto key = arg.substr(0, pos);
206 auto value = pos == std::string::npos ? std::string{} : arg.substr(pos + 1);
207 ret[key] = value;
208 }
209 return ret;
210}
211
212int usage(const char* me) {
213 std::cerr
214 << me << ": check VINTF metadata." << std::endl
215 << " Options:" << std::endl
216 << " --dump-file-list: Dump a list of directories / files on device" << std::endl
217 << " that is required to be used by --check-compat." << std::endl
218 << " -c, --check-compat: check compatibility for files under the root" << std::endl
219 << " directory specified by --root-dir." << std::endl
220 << " --rootdir=<dir>: specify root directory for all metadata." << std::endl
221 << " -D, --property <key>=<value>: specify sysprops." << std::endl
222 << " --help: show this message." << std::endl
223 << std::endl
224 << " Example:" << std::endl
225 << " # Get the list of required files." << std::endl
226 << " " << me << " --dump-file-list > /tmp/files.txt" << std::endl
227 << " # Pull from ADB, or use your own command to extract files from images"
228 << std::endl
229 << " ROOTDIR=/tmp/device/" << std::endl
230 << " cat /tmp/files.txt | xargs -I{} bash -c \"mkdir -p $ROOTDIR`dirname {}` && adb "
231 "pull {} $ROOTDIR{}\""
232 << std::endl
233 << " # Check compatibility." << std::endl
234 << " " << me << " --check-compat --rootdir=$ROOTDIR \\" << std::endl
235 << " --property ro.product.first_api_level=`adb shell getprop "
236 "ro.product.first_api_level` \\"
237 << std::endl
238 << " --property ro.boot.product.hardware.sku=`adb shell getprop "
239 "ro.boot.product.hardware.sku`"
240 << std::endl;
241 return 1;
242}
243
244int checkAllFiles(const std::string& rootdir, const Properties& props, std::string* error) {
245 hostFileFetcher.setRootDir(rootdir);
246 hostPropertyFetcher.setProperties(props);
247
248 return VintfObject::CheckCompatibility({} /* packageInfo */, error, DISABLE_RUNTIME_INFO);
249}
250
251} // namespace details
252} // namespace vintf
253} // namespace android
254
255int main(int argc, char** argv) {
256 using namespace android::vintf;
257 using namespace android::vintf::details;
258 // legacy usage: check_vintf <manifest.xml> <matrix.xml>
259 if (argc == 3) {
260 int ret = checkCompatibilityForFiles(argv[1], argv[2]);
261 if (ret >= 0) return ret;
262 }
263
264 Args args = parseArgs(argc, argv);
265
266 if (!iterateValues(args, HELP).empty()) {
267 return usage(argv[0]);
268 }
269
270 if (!iterateValues(args, DUMP_FILE_LIST).empty()) {
271 for (const auto& file : dumpFileList()) {
272 std::cout << file << std::endl;
273 }
274 return 0;
275 }
276
277 auto rootdirs = iterateValues(args, ROOTDIR);
278 auto properties = getProperties(iterateValues(args, PROPERTY));
279
280 auto checkCompat = iterateValues(args, CHECK_COMPAT);
281 if (!checkCompat.empty()) {
282 if (rootdirs.empty()) {
283 std::cerr << "Missing --rootdir option." << std::endl;
284 return usage(argv[0]);
285 }
286 int ret = COMPATIBLE;
287 for (const auto& rootdir : rootdirs) {
288 std::cerr << "Debug: checking files under " << rootdir << "..." << std::endl;
289 std::string error;
290 int compat = checkAllFiles(rootdir, properties, &error);
291 std::cerr << "Debug: files under " << rootdir
292 << (compat == COMPATIBLE
293 ? " is compatible"
294 : compat == INCOMPATIBLE ? " are incompatible"
295 : (" has encountered an error: " + error))
296 << std::endl;
297 }
298 if (ret == COMPATIBLE) {
299 std::cout << "true" << std::endl;
300 }
301 return ret;
302 }
303
304 return usage(argv[0]);
305}
diff --git a/include/vintf/DisabledChecks.h b/include/vintf/DisabledChecks.h
index 09f49a3..43ff2b5 100644
--- a/include/vintf/DisabledChecks.h
+++ b/include/vintf/DisabledChecks.h
@@ -25,6 +25,8 @@ enum DisabledChecks : int32_t {
25 ENABLE_ALL_CHECKS = 0, 25 ENABLE_ALL_CHECKS = 0,
26 // Disable AVB version check in RuntimeInfo::checkCompatibility 26 // Disable AVB version check in RuntimeInfo::checkCompatibility
27 DISABLE_AVB_CHECK = 1 << 0, 27 DISABLE_AVB_CHECK = 1 << 0,
28 // Disable RuntimeInfo <-> Framework Matrix check. This implies DISABLE_AVB_CHECK.
29 DISABLE_RUNTIME_INFO = 1 << 1,
28}; 30};
29 31
30} // namespace vintf 32} // namespace vintf
diff --git a/include/vintf/MapValueIterator.h b/include/vintf/MapValueIterator.h
index ec9fb19..c9bf4b2 100644
--- a/include/vintf/MapValueIterator.h
+++ b/include/vintf/MapValueIterator.h
@@ -98,6 +98,20 @@ struct MapIterTypes {
98 map_ref mMap; 98 map_ref mMap;
99 }; 99 };
100 100
101 template <bool is_const>
102 struct RangeImpl {
103 using iter_type = typename std::conditional<is_const, typename Map::const_iterator,
104 typename Map::iterator>::type;
105 using range_type = std::pair<iter_type, iter_type>;
106 RangeImpl(range_type r) : mRange(r) {}
107 IteratorImpl<is_const> begin() const { return mRange.first; }
108 IteratorImpl<is_const> end() const { return mRange.second; }
109 bool empty() const { return begin() == end(); }
110
111 private:
112 range_type mRange;
113 };
114
101 using ValueIterable = IterableImpl<false>; 115 using ValueIterable = IterableImpl<false>;
102 using ConstValueIterable = IterableImpl<true>; 116 using ConstValueIterable = IterableImpl<true>;
103}; 117};
@@ -116,6 +130,12 @@ ConstMultiMapValueIterable<K, V> iterateValues(const std::multimap<K, V> &map) {
116 return map; 130 return map;
117} 131}
118 132
133template <typename K, typename V>
134typename MapIterTypes<std::multimap<K, V>>::template RangeImpl<true> iterateValues(
135 const std::multimap<K, V>& map, const K& key) {
136 return map.equal_range(key);
137}
138
119} // namespace vintf 139} // namespace vintf
120} // namespace android 140} // namespace android
121 141
diff --git a/include/vintf/RuntimeInfo.h b/include/vintf/RuntimeInfo.h
index b7d3c0c..6ba8a22 100644
--- a/include/vintf/RuntimeInfo.h
+++ b/include/vintf/RuntimeInfo.h
@@ -91,7 +91,6 @@ struct RuntimeInfo {
91 protected: 91 protected:
92 virtual status_t fetchAllInformation(FetchFlags flags); 92 virtual status_t fetchAllInformation(FetchFlags flags);
93 93
94 private:
95 friend struct RuntimeInfoFetcher; 94 friend struct RuntimeInfoFetcher;
96 friend class VintfObject; 95 friend class VintfObject;
97 friend struct LibVintfTest; 96 friend struct LibVintfTest;
diff --git a/include/vintf/VintfObject.h b/include/vintf/VintfObject.h
index 7e671f0..2e260ab 100644
--- a/include/vintf/VintfObject.h
+++ b/include/vintf/VintfObject.h
@@ -151,6 +151,7 @@ public:
151 static status_t FetchOdmHalManifest(HalManifest* out, std::string* error = nullptr); 151 static status_t FetchOdmHalManifest(HalManifest* out, std::string* error = nullptr);
152 static status_t FetchOneHalManifest(const std::string& path, HalManifest* out, 152 static status_t FetchOneHalManifest(const std::string& path, HalManifest* out,
153 std::string* error = nullptr); 153 std::string* error = nullptr);
154 static status_t FetchFrameworkHalManifest(HalManifest* out, std::string* error = nullptr);
154 155
155 static bool isHalDeprecated(const MatrixHal& oldMatrixHal, 156 static bool isHalDeprecated(const MatrixHal& oldMatrixHal,
156 const CompatibilityMatrix& targetMatrix, 157 const CompatibilityMatrix& targetMatrix,
@@ -187,8 +188,17 @@ extern const std::string kVendorMatrix;
187extern const std::string kOdmManifest; 188extern const std::string kOdmManifest;
188extern const std::string kVendorLegacyManifest; 189extern const std::string kVendorLegacyManifest;
189extern const std::string kVendorLegacyMatrix; 190extern const std::string kVendorLegacyMatrix;
191extern const std::string kSystemLegacyManifest;
190extern const std::string kSystemLegacyMatrix; 192extern const std::string kSystemLegacyMatrix;
191 193
194// Convenience function to dump all files and directories that could be read
195// by calling Get(Framework|Device)(HalManifest|CompatibilityMatrix). The list
196// include files that may not actually be read when the four functions are called
197// because some files have a higher priority than others. The list does NOT
198// include "files" (including kernel interfaces) that are read when GetRuntimeInfo
199// is called.
200std::vector<std::string> dumpFileList();
201
192} // namespace details 202} // namespace details
193 203
194} // namespace vintf 204} // namespace vintf
diff --git a/test/Android.bp b/test/Android.bp
index 6777ca3..50afb63 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -51,6 +51,8 @@ cc_test {
51 host_supported: true, 51 host_supported: true,
52 native_coverage: true, 52 native_coverage: true,
53 srcs: [ 53 srcs: [
54 "RuntimeInfo-fake.cpp",
55 "utils-fake.cpp",
54 "vintf_object_tests.cpp", 56 "vintf_object_tests.cpp",
55 ], 57 ],
56 shared_libs: [ 58 shared_libs: [
@@ -64,7 +66,8 @@ cc_test {
64 "libgtest", 66 "libgtest",
65 "libgmock", 67 "libgmock",
66 "libhidl-gen-utils", 68 "libhidl-gen-utils",
67 "libvintftest", 69 "libvintf_common",
70 "libz",
68 ], 71 ],
69 cflags: [ 72 cflags: [
70 "-O0", 73 "-O0",
diff --git a/test/RuntimeInfo-fake.cpp b/test/RuntimeInfo-fake.cpp
index c13eac2..0efcae7 100644
--- a/test/RuntimeInfo-fake.cpp
+++ b/test/RuntimeInfo-fake.cpp
@@ -14,13 +14,16 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include "RuntimeInfo.h" 17#include "utils-fake.h"
18 18
19namespace android { 19namespace android {
20namespace vintf { 20namespace vintf {
21 21namespace details {
22// Fake implementation used for testing. 22status_t MockRuntimeInfo::doFetch(RuntimeInfo::FetchFlags) {
23status_t RuntimeInfo::fetchAllInformation(RuntimeInfo::FetchFlags) { 23 if (failNextFetch_) {
24 failNextFetch_ = false;
25 return android::UNKNOWN_ERROR;
26 }
24 mOsName = "Linux"; 27 mOsName = "Linux";
25 mNodeName = "localhost"; 28 mNodeName = "localhost";
26 mOsRelease = "3.18.31-g936f9a479d0f"; 29 mOsRelease = "3.18.31-g936f9a479d0f";
@@ -37,5 +40,6 @@ status_t RuntimeInfo::fetchAllInformation(RuntimeInfo::FetchFlags) {
37 return OK; 40 return OK;
38} 41}
39 42
43} // namespace details
40} // namespace vintf 44} // namespace vintf
41} // namespace android 45} // namespace android
diff --git a/test/utils-fake.cpp b/test/utils-fake.cpp
index 151b3bf..38f6ab0 100644
--- a/test/utils-fake.cpp
+++ b/test/utils-fake.cpp
@@ -14,7 +14,7 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include "utils.h" 17#include "utils-fake.h"
18 18
19namespace android { 19namespace android {
20namespace vintf { 20namespace vintf {
@@ -28,6 +28,18 @@ PartitionMounter* gPartitionMounter = nullptr;
28 28
29ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = nullptr; 29ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = nullptr;
30 30
31MockPropertyFetcher::MockPropertyFetcher() {
32 using namespace ::testing;
33 using namespace std::placeholders;
34 ON_CALL(*this, getProperty(_, _))
35 .WillByDefault(Invoke(std::bind(&PropertyFetcher::getProperty, real_, _1, _2)));
36}
37
38MockPropertyFetcher* gPropertyFetcher = nullptr;
39const PropertyFetcher& getPropertyFetcher() {
40 return *gPropertyFetcher;
41}
42
31} // namespace details 43} // namespace details
32} // namespace vintf 44} // namespace vintf
33} // namespace android 45} // namespace android
diff --git a/test/utils-fake.h b/test/utils-fake.h
index e2b2706..0253bca 100644
--- a/test/utils-fake.h
+++ b/test/utils-fake.h
@@ -96,13 +96,7 @@ class MockRuntimeInfo : public RuntimeInfo {
96 .WillByDefault(Invoke(this, &MockRuntimeInfo::doFetch)); 96 .WillByDefault(Invoke(this, &MockRuntimeInfo::doFetch));
97 } 97 }
98 MOCK_METHOD1(fetchAllInformation, status_t(RuntimeInfo::FetchFlags)); 98 MOCK_METHOD1(fetchAllInformation, status_t(RuntimeInfo::FetchFlags));
99 status_t doFetch(RuntimeInfo::FetchFlags flags) { 99 status_t doFetch(RuntimeInfo::FetchFlags flags);
100 if (failNextFetch_) {
101 failNextFetch_ = false;
102 return android::UNKNOWN_ERROR;
103 }
104 return RuntimeInfo::fetchAllInformation(flags);
105 }
106 void failNextFetch() { failNextFetch_ = true; } 100 void failNextFetch() { failNextFetch_ = true; }
107 101
108 private: 102 private:
@@ -118,6 +112,16 @@ class MockRuntimeInfoFactory : public ObjectFactory<RuntimeInfo> {
118 std::shared_ptr<MockRuntimeInfo> object_; 112 std::shared_ptr<MockRuntimeInfo> object_;
119}; 113};
120 114
115class MockPropertyFetcher : public PropertyFetcher {
116 public:
117 MockPropertyFetcher();
118 MOCK_CONST_METHOD2(getProperty, std::string(const std::string&, const std::string&));
119
120 private:
121 PropertyFetcher real_;
122};
123extern MockPropertyFetcher* gPropertyFetcher;
124
121} // namespace details 125} // namespace details
122} // namespace vintf 126} // namespace vintf
123} // namespace android 127} // namespace android
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index 3d834eb..d2f62d1 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -21,10 +21,6 @@
21#include <stdio.h> 21#include <stdio.h>
22#include <unistd.h> 22#include <unistd.h>
23 23
24#ifdef LIBVINTF_TARGET
25#include <android-base/properties.h>
26#endif
27
28#include <android-base/strings.h> 24#include <android-base/strings.h>
29#include <vintf/VintfObject.h> 25#include <vintf/VintfObject.h>
30#include <vintf/parse_string.h> 26#include <vintf/parse_string.h>
@@ -290,9 +286,9 @@ static MockFileFetcher &fetcher() {
290class VintfObjectTestBase : public testing::Test { 286class VintfObjectTestBase : public testing::Test {
291 protected: 287 protected:
292 virtual void SetUp() { 288 virtual void SetUp() {
293#ifdef LIBVINTF_TARGET 289 productModel = "fake_sku";
294 productModel = android::base::GetProperty("ro.boot.product.hardware.sku", ""); 290 ON_CALL(*gPropertyFetcher, getProperty("ro.boot.product.hardware.sku", _))
295#endif 291 .WillByDefault(Return(productModel));
296 } 292 }
297 virtual void TearDown() { 293 virtual void TearDown() {
298 Mock::VerifyAndClear(&mounter()); 294 Mock::VerifyAndClear(&mounter());
@@ -724,7 +720,6 @@ bool containsOdmProductManifest(const std::shared_ptr<const HalManifest>& p) {
724 720
725class DeviceManifestTest : public VintfObjectTestBase { 721class DeviceManifestTest : public VintfObjectTestBase {
726 protected: 722 protected:
727 virtual void SetUp() override {}
728 723
729 // Expect that /vendor/etc/vintf/manifest.xml is fetched. 724 // Expect that /vendor/etc/vintf/manifest.xml is fetched.
730 void expectVendorManifest() { expectFetch(kVendorManifest, vendorEtcManifest); } 725 void expectVendorManifest() { expectFetch(kVendorManifest, vendorEtcManifest); }
@@ -986,5 +981,8 @@ int main(int argc, char** argv) {
986 std::make_shared<NiceMock<MockRuntimeInfo>>()); 981 std::make_shared<NiceMock<MockRuntimeInfo>>());
987 gRuntimeInfoFactory = &runtimeInfoFactory; 982 gRuntimeInfoFactory = &runtimeInfoFactory;
988 983
984 NiceMock<MockPropertyFetcher> properties;
985 gPropertyFetcher = &properties;
986
989 return RUN_ALL_TESTS(); 987 return RUN_ALL_TESTS();
990} 988}
diff --git a/utils-common.cpp b/utils-common.cpp
new file mode 100644
index 0000000..3e7e736
--- /dev/null
+++ b/utils-common.cpp
@@ -0,0 +1,42 @@
1
2/*
3 * Copyright (C) 2017 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "utils.h"
19
20// Default implementations for classes defined in utils.h
21
22namespace android {
23namespace vintf {
24namespace details {
25
26std::string PropertyFetcher::getProperty(const std::string&,
27 const std::string& defaultValue) const {
28 return defaultValue;
29}
30
31uint64_t PropertyFetcher::getUintProperty(const std::string&, uint64_t,
32 uint64_t defaultValue) const {
33 return defaultValue;
34}
35
36bool PropertyFetcher::getBoolProperty(const std::string&, bool defaultValue) const {
37 return defaultValue;
38}
39
40} // namespace details
41} // namespace vintf
42} // namespace android
diff --git a/utils.cpp b/utils.cpp
index 2b0cb37..5b2bb7d 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -16,6 +16,10 @@
16 16
17#include "utils.h" 17#include "utils.h"
18 18
19#ifdef LIBVINTF_TARGET
20#include <android-base/properties.h>
21#endif
22
19namespace android { 23namespace android {
20namespace vintf { 24namespace vintf {
21namespace details { 25namespace details {
@@ -29,6 +33,32 @@ PartitionMounter* gPartitionMounter = &partitionMounter;
29static ObjectFactory<RuntimeInfo> runtimeInfoFactory; 33static ObjectFactory<RuntimeInfo> runtimeInfoFactory;
30ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = &runtimeInfoFactory; 34ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = &runtimeInfoFactory;
31 35
36#ifdef LIBVINTF_TARGET
37class DevicePropertyFetcher : public PropertyFetcher {
38 public:
39 std::string getProperty(const std::string& key,
40 const std::string& defaultValue) const override {
41 return android::base::GetProperty(key, defaultValue);
42 }
43 uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
44 uint64_t max) const override {
45 return android::base::GetUintProperty(key, defaultValue, max);
46 }
47 bool getBoolProperty(const std::string& key, bool defaultValue) const override {
48 return android::base::GetBoolProperty(key, defaultValue);
49 }
50};
51const PropertyFetcher& getPropertyFetcher() {
52 static DevicePropertyFetcher fetcher;
53 return fetcher;
54}
55#else
56const PropertyFetcher& getPropertyFetcher() {
57 static PropertyFetcher fetcher;
58 return fetcher;
59}
60#endif
61
32} // namespace details 62} // namespace details
33} // namespace vintf 63} // namespace vintf
34} // namespace android 64} // namespace android
diff --git a/utils.h b/utils.h
index 305a018..783d40b 100644
--- a/utils.h
+++ b/utils.h
@@ -141,6 +141,18 @@ inline Level convertFromApiLevel(size_t apiLevel) {
141 } 141 }
142} 142}
143 143
144class PropertyFetcher {
145 public:
146 virtual ~PropertyFetcher() = default;
147 virtual std::string getProperty(const std::string& key,
148 const std::string& defaultValue = "") const;
149 virtual uint64_t getUintProperty(const std::string& key, uint64_t defaultValue,
150 uint64_t max = UINT64_MAX) const;
151 virtual bool getBoolProperty(const std::string& key, bool defaultValue) const;
152};
153
154const PropertyFetcher& getPropertyFetcher();
155
144} // namespace details 156} // namespace details
145} // namespace vintf 157} // namespace vintf
146} // namespace android 158} // namespace android